Reputation: 63
I am trying to get the IPv4 addresses from a text file using the following command:
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
.
This will display the valid IP addresses but will also display the valid part from a longer invalid IP which I don't want.
Input example:
IP address one is 192.168.1.1, ip 2 is 192.168.1.2.
192.168.1.3 192.168.1.10.1
Output I get:
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.10
Output I want:
192.168.1.1
192.168.1.2
192.168.1.3
Upvotes: 2
Views: 108
Reputation: 627507
You need to exclude all matches where a <digit>.
is present immediately before and a .<digit>
immediately after the IP.
That is why you need a GNU grep
with the following regex:
grep -Po '\b(?<!\d\.)(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b(?!\.\d)' file
The \b(?<!\d\.)
at the start matches a word boundary first (it means there must be no letter, digit or _
immediately to the left of the current location) and there must be no digit and .
sequence there, either.
The \b(?!\.\d)
at the end matches a word boundary first (here, it means there must be no letter, digit or _
immediately to the right of the current location) and there must be no .
+ digit sequence there, either.
See an online grep
demo:
s="IP address one is 192.168.1.1, ip 2 is 192.168.1.2.
192.168.1.3 192.168.1.10.1"
grep -Po '\b(?<!\d\.)(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b(?!\.\d)' <<< "$s"
Output:
192.168.1.1
192.168.1.2
192.168.1.3
See the PCRE regex demo.
Upvotes: 2