views:

68

answers:

3

hi dear friends and good morning

The following question may be complicated and critical for my systems

I have 4 Linux machines with cluster

My target is to find all kind of IP address (xxx.xxx.xxx.xxx) in every file in the linux system

remark: need to scan each file in the linux system and verify if the file include IP address if yes need to print the IP

as the following

more /etc/inet/file.example1

 182.23.2.4
 255.255.0.0
 10.10.1.1
 19.2.*.*
 127.0.0.1

more /etc/dir/file1.example2

 1.1.1.1 TCP

Etc.................

Can I get some creative suggestion that search all IP address and print them

lidia

A: 

On Linux (where grep supports recursive search) and with assumption of at most 1 IP address per line the code below would work (--include & --exclude are optional, search starts recursively from $PWD).

grep -r -P [--include=PATTERN --exclude=PATTERN]\
  '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' $PWD |\
  perl -ne 'print "$1\n" if /\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/;'
bobah
but I need to also scan all files your example give me to find IP only on one file and I need to find and scan all files in the linux sys
lidia
@lidia - It works recursively. If you replace $PWD with / it will find all IP addresses in all files, though this will take ages
bobah
OK I get all IP address nut I need to get also the file that relevant for the IP address , how to change your syntax in order to get the IP and the full path of file also?
lidia
change Perl part to 'print "$1 $2\n" if /^(.*?):.*?\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/;'
bobah
+2  A: 

When asked to match an IP address, many will write

/\d+\.\d+\.\d+\.\d+/

but this will give false positives. In Jeffrey Friedl's Mastering Regular Expressions, the author gives a pattern for matching IP addresses that's much more careful. The code below borrows from Friedl to force not an arbitrary run of digits but on the range from 0 to 255, requires that an address begin and end at word boundaries (\b), and disallows the address 0.0.0.0.

With no arguments, the code below defaults to the current directory for the beginning of its search. To search all files, supply the root directory as an argument. Opening each path that find outputs, we then search each line for an IP address and print all hits along with their respective paths.

Note how the code uses local to transparently switch back and forth between the NUL character and newline for the record separator $/. This is necessary because the find's -print0 action separates filenames with '\0', but '\n' is the line terminator. With -T, we search text files only.

#! /usr/bin/perl

use warnings;
no warnings 'exec';
use strict;

my $octet = qr/[01]?\d\d?|2[0-4]\d|25[0-5]/;

my $ip = qr/ \b
             (?!0+\.0+\.0+\.0+\b)
             $octet(?:\.$octet){3}
             \b
           /x;

@ARGV = (".") unless @ARGV;
open my $find, "-|", "find", @ARGV, "-type", "f", "-print0"
  or die "$0: failed to start find: $!\n";

$/ = "\0";
while (defined(my $path = <$find>)) {
  chomp $path;
  next unless -T $path;
  if (open my $fh, "<", $path) {
    local $/ = "\n";
    while (<$fh>) {
      print "$path: $_" if /$ip/;
    }
    close $fh;
  }
  else {
    warn "$0: open $path: $!\n";
  }
}
Greg Bacon
very cool and strong perl script , I need to make some test on my system so I will send you my last idea again THX
lidia
by the way if I want to search only the IP - 123.34.5.23
lidia
so I need to set: my $octet = qr/123.34.5.23/; ?
lidia
@lidia If you're looking for a particular IP address, then use straightforward `find / -type f -print0 | xargs -0 grep -H -w '123\.34\.5\.23'`
Greg Bacon
yes I want to use both , but I mean that I want to use your script for particular IP and generic IP as you write ,
lidia
@gbacon, why use xargs? find can execute grep directly `find / -type f -exec grep -H -w '10.20.30.40' {} +`
Ven'Tatsu
A: 

For searching in files I almost always use ack.

A simple pattern that, as gbacon notes, will result in false positives:

ack -uo '\b\d+\.\d+\.\d+\.\d+\b' /

The -u option makes ack match unrestricted, ack will usually skip version control metadata directories like .svn and backup files. The -o option will print out the portion of each line that matched instead of the whole line that matched.

The same idea but using gbacon's better pattern:

ack -uo '\b(?!0+\.0+\.0+\.0+\b)(?:[01]?\d\d?|2[0-4]\d|25[0-5])(?:\.(?:[01]?\d\d?|2[0-4]\d|25[0-5])){3}\b' /

To match a specific address you can use --literal to specify the exact text to match.

ack -uo --literal 123.34.5.23 /

Ven'Tatsu