14

I have a script that generates some output. I want to check that output for any IP address like

159.143.23.12
134.12.178.131
124.143.12.132

if (IPs are found in <file>)
then // bunch of actions //
else // bunch of actions //

Is fgrep a good idea?

I have bash available.

  • use grep , egrep , awk , or sed , whatever u like – Ijaz Ahmad Khan Jul 18 '16 at 10:30
  • Could you help with the syntax please? I mean how does it search for a random IP. How to describe the pattern? I would be looking for any IP address, not a particular address. – Koshur Jul 18 '16 at 10:31
  • 5
    Is that only IPv4 addresses in quad-decimal notation? Could they be written like 0010.0000.0000.0001? May the file otherwise contain things that look like IP addresses like version numbers (soft-1.2.1100.1.tar.gz, network specifications (10.0.0.0/24), 1.2.3.4.5)? Would you accept a solution that is positive on 333.444.555.666? Or 0377.0377.0377.0377 (a valid quad-octal IP address)? – Stéphane Chazelas Jul 18 '16 at 10:47
  • If bash is available, then awk usually is also, so this might work for you: awk '/([0-9]{2,3}\.){3}/ {print $5 "\t" $1}' (This one-liner translates the output of host XFR list to /etc/hosts format.) – Mark Hudson Nov 15 '17 at 23:23
22

Yes , You have lot of options/tools to use. I just tried this , it works:

ifconfig | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"

so you can use grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" to grep the ip addresses from your output.

  • Thanks. This works. Can you explain a bit? Is this a regular expression? – Koshur Jul 18 '16 at 10:39
  • Yes this is a regular expression used in bash with grep , you are just looking for three digits pattern separated by dots. you can play with by changing the numbers in {1,2} for 2 consecutive digits and so on – Ijaz Ahmad Khan Jul 18 '16 at 10:43
  • One can also use "\b([0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9][0-9]?" to find CIDRs (assuming they are valid) – vikas027 Sep 7 '18 at 0:16
2

starting my answer based on this answer:

Yes , You have lot of options/tools to use. I just tried this , it works:

ifconfig | grep -oE "\b([0-9]{1,3}.){3}[0-9]{1,3}\b" a so you can use grep -oE "\b([0-9]{1,3}.){3}[0-9]{1,3}\b" to grep the ip addresses from your output.

and converting the answer to full length IPv6, etc...:

fgrep -oE "\b([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}\b" -- file

if you want to keep the /nnn if it's there:

fgrep -oE "\b([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}(/[0-9]{1,3}){0,1}\b" -- file

and also there's the shortened version of IPv6 that includes '::'.

for more IPv6 answers you can look here: https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses

  • fgrep is the old name for a variant of grep that ignores pattern matching. I'd recommend you use grep (or even egrep) instead, especially as you're clearly wanting pattern matching. – roaima Jul 18 '16 at 19:59
2

If your file is called e.g ips you can write somethinng like:

while read -r ip
    do
        if [[ $ip == "$1" ]]; then
            shift
            printf '%s\n' 'action to take if match found'
        else
            printf '%s\n' 'action to take if match not found'
        fi
    done < ips

Then you can pass the parameters as follow the the script

./myscript 159.143.23.12 134.12.178.131 124.143.12.132 124.143.12.132
0

Redirect that output to some outputFile

Simply grep it with pattern as,

grep -sE "159.143.23.12|134.12.178.131|124.143.12.132" <outputFile>
  • 4
    Note that . is a regular expression operator and needs escaping for it to be treated literally – Stéphane Chazelas Jul 18 '16 at 10:49
  • 1
    Those aren't patterns, those are literals. Not a useful answer since the OP specified "any IP." – Mark Hudson Nov 15 '17 at 23:18
0

If you have the list of IPs in a file, one per line, grep already has the convenient -f option:

$ man fgrep | grep file= -A1
       -f FILE, --file=FILE
              Obtain patterns from FILE, one per line.  The empty file contains zero patterns, and therefore matches nothing.  (-f is specified by POSIX.)

This may cause a few false positives due to strings optionally followed by another number to make it a different IP. Lots of things you can do about it, depending on your case you may or may not decide to worry.

0

Tested in SmartOS (a variant of Solaris), hopefully should work in other *nix environments:

egrep '(([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])'

Example:

$ cat >file.txt
IP1: 192.168.1.1
IP2: 261.480.201.311
IP3: 1012.680.921.3411

$ egrep '(([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])' file.txt
IP1: 192.168.1.1

This pattern matches only valid IPv4, i.e, x.x.x.x where x range from 0-255. Should you need to extract only the matched IP, add an -o option to the above command. You could embed this command in a bash script and presumably in other shell scripts as well. And, if egrep fails, try grep -E ...

Using it in a (bash) shell script:

ip=$(egrep -o '(([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])' file.txt) echo $ip

0

I think my answer to another post is better suited here. Thanks to this post and others like it I came up with this, that looks for the correct IP format, then gets rid of all the lines that contain 256 or higher. Replace the IP with something that is non-valid to see no output instead:

echo '255.154.12.231' | grep -E '(([0-9]{1,3})\.){3}([0-9]{1,3}){1}' | grep -vE '25[6-9]|2[6-9][0-9]|[3-9][0-9][0-9]'

The first grep was probably found in this post and it checks for any numbers from 0-999 in the format X.X.X.X

The second grep removes lines with numbers 256-999, thus leaving only valid format IPs, so I thought

BUT... As pointed out by G-Man, I was in error by assuming the IP would be on its own line. Most always though, there will be a space or another divider to look for on either side of the IP. The spaces/dividers can be removed with sed or other means after the IP is found. I also added -o to the first grep:

echo ' 1234.5.5.4321 ' | grep -Eo ' (([0-9]{1,3})\.){3}([0-9]{1,3}){1} ' | grep -vE '25[6-9]|2[6-9][0-9]|[3-9][0-9][0-9]' | sed 's/ //'

echo ' 234.5.5.432 ' | grep -Eo ' (([0-9]{1,3})\.){3}([0-9]{1,3}){1} ' | grep -vE '25[6-9]|2[6-9][0-9]|[3-9][0-9][0-9]' | sed 's/ //'

The first will give no output, while the second does and the spaces are stripped.

  • Suppose I have 500 addresses, ranging from 10.0.0.1 to 10.0.1.244.  Your second grep would throw out that line because of the “500”.  (The question never said that the IP address(es) in the file, if any, would be on a line by themselves.)  On the other hand, it will accept 1234.1.1.1 and 1.1.1.1234. But aside from that, not bad. – G-Man Apr 5 '18 at 5:07

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.