1

I was trying to create a regex that match a ip adress, or a ip adress with netmask: something like 8.8.8.8/24

if ! [[ $SOURCE =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ $SOURCE =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$ ]];then
                echo ERROR: Invalid Source
                exit 1
fi

The first part matchted well, the second, with the netmask doest match.. Anyone know why?

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
tso
  • 187
  • 4
  • 13

1 Answers1

1

Define the regexps in separate variables and use a single pattern:

SOURCE="8.8.8.8"
RX="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2})?$"
if ! [[ $SOURCE =~ $RX ]];then
                echo ERROR: Invalid Source
                exit 1
fi

See the online demo here.

Pattern explanation:

  • ^ - start of string
  • [0-9]{1,3}\. - 1 to 3 digits followed with a literal dot
  • [0-9]{1,3}\.[0-9]{1,3}\. - same as above, 2 times
  • [0-9]{1,3} - 1 to 3 digits (this matches the IP string)
  • (/[0-9]{1,2})? - an optional (1 or 0 occurrences) sequence of:
    • / - a slash (since it is not a special char, it needs no escaping)
    • [0-9]{1,2} - 1 to 2 digits
  • $ - end of string.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • RX1="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" RX2="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2})?$" if ! [[ $SOURCE1 =~ $RX1 ]] || [[ $SOURCE =~ $RX2 ]];then echo ERROR: Invalid Source exit 1 fi – tso Mar 14 '17 at 13:35
  • You do not need to use 2 regexps for this check, use one. – Wiktor Stribiżew Mar 14 '17 at 13:36
  • 1
    Worked! Thank you! – tso Mar 14 '17 at 13:38
  • Note that placing the pattern into a variable is the safest way of passing a regex inside `[[...]]`, as inside the RHS, variable expansion can occur. See [this SO answer](http://stackoverflow.com/a/18710850/3832970). – Wiktor Stribiżew Mar 14 '17 at 13:40