grep print lines matching a pattern

Regular Expression to Match IP Addresses

Use the following regular expression to match IPv4 addresses (actually it matches all expressions from to 999.999.999.999).



Grep IP Addresses

Parse a file and print all expressions that match a range between and 999.999.999.999.

grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" file.txt

This regular expression is quite simple but you should understand that not all matches are technically valid IP addresses.

Let’s find only valid IP addresses with the second regular expression.

Match only Valid IPv4 Addresses

Use the following regular expression to find and validate the IPv4 addresses :


Grep Only Valid IP Addresses

Find and extract only valid IP addresses from a file :

grep -E -o "(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]?)\.(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]?)" file.txt
# ---------------------------------------------------------
# ---    :

grep sometext <filename> | tr -d "\n"
# ---------------------------------------------------------
# ---------------------------------------------------------
# ---    :

First, you need to protect the pattern from expansion by the shell. The easiest way to do that is to put single quotes around it. Single quotes prevent expansion of anything between them (including backslashes); the only thing you can't do then is have single quotes in the pattern.

grep 'foo*' *.txt

If you do need a single quote, you can write it as '\'' (end string literal, literal quote, open string literal).

grep 'foo*'\''bar' *.txt

Second, grep supports two syntaxes for patterns. The old, default syntax (basic regular expressions) doesn't support the alternation (|) operator, though some versions have it as an extension, but written with a backslash.

grep 'foo\|bar' *.txt

The portable way is to use the newer syntax, extended regular expressions. You need to pass the -E option to grep to select it. On Linux, you can also type egrep instead of grep -E (on other unices, you can make that an alias).

grep -E 'foo|bar' *.txt

Another possibility when you're just looking for any of several patterns (as opposed to building a complex pattern using disjunction) is to pass multiple patterns to grep. You can do this by preceding each pattern with the -e option.

grep -e foo -e bar *.txt

# ---------------------------------------------------------
# ---------------------------------------------------------
# ---    :

agrep can do it with this syntax:

agrep 'pattern1;pattern2'

With GNU grep, when built with PCRE support, you can do:

grep -P '^(?=.*pattern1)(?=.*pattern2)'

With ast grep:

grep -X '.*pattern1.*&.*pattern2.*'

(adding .*s as <x>&<y> matches strings that match both <x> and <y> exactly, a&b would never match as there's no such string that can be both a and b at the same time).

If the patterns don't overlap, you may also be able to do:

grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'

The best portable way is probably with awk as already mentioned:

awk '/pattern1/ && /pattern2/'

With sed:

sed -e '/pattern1/!d' -e '/pattern2/!d'

Please beware that all those will have different regular expression syntax.
# ---------------------------------------------------------

Option Description
-E, –extended-regexp Use extended regular expression
-o, –only-matching Print IP addresses only

Omit -o option to print lines that contains IP addresses.