I am trying to match IP addresses found in the output of traceroute
by means of a regex. I'm not trying to validate them because it's safe enough to assume traceroute
is valid (i.e. is not outputting something like 999.999.999.999
. I'm trying the following regex:
([0-9]{1,3}.?){4}
I'm testing it in regex101 and it does validate an IP address. However, when I try
echo '192.168.1.1 foobar' | grep '([0-9]{1,3}.?){4}'
I get nothing. What am I missing?
You used a POSIX ERE pattern, but did not pass -E
option to have grep
use the POSIX ERE flavor. Thus, grep
used POSIX BRE instead, where you need to escape {n,m}
quantifier and (...)
to make them be parsed as special regex operators.
Note you need to escape a .
so that it could only match a literal dot.
To make your pattern work with grep
the way you wanted you could use:
grep -E '([0-9]{1,3}\.?){4}' # POSIX ERE
grep '\([0-9]\{1,3\}\.\?\)\{4\}' # POSIX BRE version of the same regex
See an online demo.
However, this regex will also match a string of several digits because the .
is optional.
You may solve it by unrolling the pattern as
grep -E '[0-9]{1,3}(\.[0-9]{1,3}){3}' # POSIX ERE
grep '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' # POSIX BRE
See another demo.
Basically, it matches:
[0-9]{1,3}
- 1 to 3 occurrences of any ASCII digit(\.[0-9]{1,3}){3}
- 3 occurrences of:
\.
- a literal .
[0-9]{1,3}
- 1 to 3 occurrences of any ASCII digitTo make sure you only match valid IPs, you might want to use a more precise IP matching regex:
grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b' # POSIX ERE
See this online demo.
You may further tweak it with word boundaries (can be \<
/ \>
or \b
), etc.
To extract the IPs use -o
option with grep
: grep -oE 'ERE_pattern' file
/ grep -o 'BRE_pattern' file
.
That regex wont work. Use this instead.
@Olian04: I understand what you mean, I just translated OP regex into POSIX BRE/ERE. Edited.
@Olian04 Or a little shorter:
([0-9]{1,3}\.){3}[0-9]{1,3}
. Still, this doesn't catch broken IP addresses (e.g. 256.256.256.256).@VictorZamanian You might want to use a more precise IP matching regex. The answer just points out how to fix the current OP approach. There are more ways to match IPs and all that depends on what the use case is.