2

I need to be able to validate a group of IP addresses that will appear in a file that looks like this:

IP_SUBNETS=['10.1.111.0','10.2.111.0','10.2.123.0']

I'd like to write a regular expression that will allow n number of ip addresses, as long as they are delimited by "," and have single quotes around them, and the entire "list" is opened and closed by square brackets.

I've been able to find some bash examples of regular expressions but I'm having a hard time finding something that works for busybox.

so far this is what i have:

grep IP_SUBNETS myfile | cut -c 12- | grep '^\[[0-9].'

But i can't seem to get the grouping right. aka one group per subnet.

EDIT 1

#!/bin/sh
iplist=['10.112.123.0'] 
pass="$(echo $iplist | grep -E '^\[(([0-9]{1,3}\.){3}[0-9]{1,3},)*([0-9]{1,3}\.){3}[0-9]{1,3}\]$'"
echo "$pass"
6
  • kind of confused why you're grepping for IP_SUBNETS twice
    – Jeff Schaller
    Sep 12, 2017 at 17:43
  • what exactly is your input & output here? are you validating that the "IP_SUBNETS" line contains (any) list of syntactically correct IP's? Or that it contains given IPs?
    – Jeff Schaller
    Sep 12, 2017 at 17:44
  • @JeffSchaller sorry, you're right. that was a typo as i was writing this post. And good question. I just need to ensure that the list contains any legit IP address. aka. syntax check vs. the specific addresses listed in my example above.
    – dot
    Sep 12, 2017 at 17:47
  • You need to quote $iplist — pass="$(echo "$iplist" | grep -E … also you have a missing ) at the end before the close "
    – derobert
    Sep 12, 2017 at 19:09
  • @derobert I'm afraid that doesn't change the error message.
    – dot
    Sep 12, 2017 at 19:10

1 Answer 1

1

Something like this works here:

busybox grep -E '^\[(([0-9]{1,3}\.){3}[0-9]{1,3},)*([0-9]{1,3}\.){3}[0-9]{1,3}\]$'

(busybox isn't my default grep, hence the "busybox" prefix).

That should mostly validate your list, though it isn't perfect. E.g., it'll accept 300.1.2.4 as a valid IP address. The regexp to fully validate that four dot-separated numbers represent a valid subnet start address would be much more complicated.

To break it down: First, note that part of it is repeated. Call that I for a second. Then you can see it's ^\[(I,)*I\]$ which gets you your comma-separated list of Is, with brackets around the entire list. If you then look at what I is, it's ([0-9]{1,3}\.){3}[0-9]{1,3} which is simpler if you notice another repeated pattern, O = [0-9]{1,3}. It's then (O.){1,3}O ... which is your four decimal-separated octets. In a shell script, you can of course use variables to build the pattern from these simpler building blocks—a great aid to readability and maintainability.

I tested with the following test data (with expected result as a comment, not actually in the test data file):

1.2.3.4                          # bad: no brackets
[1.2.3.4]                        # good
[1.2.3.44]                       # good
[1.2.3.4                         # bad: missing bracket
1.2.3.4]                         # bad: missing bracket
[1.2.3.4,]                       # bad: empty item
[1.2.3.4,5.6.7.8]                # good
[1.2.3.4,5.6.7.8,]               # bad: empty item
[1.2.3.4,5.6.7.E]                # bad: E is not a number
[1.2.3.4,,5.6.7.8]               # bad: empty item
[1.2.3.1234]                     # bad: 1234 is more than 3 digits

edit: you could use O = ([0-9]{1,2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5]) — there may be a simpler way to write that, not sure — to only take numbers 0–255; that leads to a much longer pattern:

busybox grep -E '^\[((([0-9]{1,2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]{1,2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5]),)*(([0-9]{1,2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]{1,2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\]$'

... which may or may not be worth it, depending on how important it is to fully validate them.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.