Find the answer to your Linux question:
Results 1 to 6 of 6
Hello, I'm having some problems using grep to match IP addresses. At first I was attempting to learn how to do it on my own, but I gave up and ...
  1. #1
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162

    Regular expressions to match IP addresses

    Hello, I'm having some problems using grep to match IP addresses. At first I was attempting to learn how to do it on my own, but I gave up and Google'd some solutions. The problem is, none of them work either. The first one I tried is this beast:

    Code:
    \b(?:(?: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
    This didn't work because of the "(" characters, yet when I tried to escape them, it didn't work either.

    Code:
    grep -e [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ./ips
    This one is less accurate, but I figured it would work, no dice

    Code:
    grep: [0-9]1.[0-9]1.[0-9]1.[0-9]3: No such file or directory
    grep: [0-9]1.[0-9]1.[0-9]1.[0-9]3: No such file or directory
    grep: [0-9]1.[0-9]1.[0-9]3.[0-9]1: No such file or directory
    grep: [0-9]1.[0-9]1.[0-9]3.[0-9]3: No such file or directory
    grep: [0-9]1.[0-9]3.[0-9]1.[0-9]1: No such file or directory
    grep: [0-9]1.[0-9]3.[0-9]1.[0-9]3: No such file or directory
    grep: [0-9]1.[0-9]3.[0-9]3.[0-9]1: No such file or directory
    grep: [0-9]1.[0-9]3.[0-9]3.[0-9]3: No such file or directory
    grep: [0-9]3.[0-9]1.[0-9]1.[0-9]1: No such file or directory
    grep: [0-9]3.[0-9]1.[0-9]1.[0-9]3: No such file or directory
    grep: [0-9]3.[0-9]1.[0-9]3.[0-9]1: No such file or directory
    grep: [0-9]3.[0-9]1.[0-9]3.[0-9]3: No such file or directory
    grep: [0-9]3.[0-9]3.[0-9]1.[0-9]1: No such file or directory
    grep: [0-9]3.[0-9]3.[0-9]1.[0-9]3: No such file or directory
    grep: [0-9]3.[0-9]3.[0-9]3.[0-9]1: No such file or directory
    grep: [0-9]3.[0-9]3.[0-9]3.[0-9]3: No such file or directory
    I am not a genius when it comes to grep, so there is probably something very simple I am missing. Can anyone help please?

  2. #2
    Linux Guru anomie's Avatar
    Join Date
    Mar 2005
    Location
    Texas
    Posts
    1,692
    Try single-quoting (') your regexps.

  3. #3
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    First off, those appear to be different sorts of regular expressions. The first appears to be Perl syntax, while the second is a mix of POSIX and Extended POSIX.

    Your problem with the second is that Bash is taking the '{'s and '}'s away. Try escaping them on the commandline.

    For instance, using Perl regular expressions, this is the easiest way:
    Code:
    \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
    Using Extended POSIX regular expressions (enabled by using 'egrep' instead of 'grep'), you could do:
    Code:
    [:digit:]{1,3}\.[:digit:]{1,3}\.[:digit:]{1,3}\.[:digit:]{1,3}
    Having said all of this, there are a few problems. For instance, both of these would accept 300.1.1.1, which is obviously not a valid regular IP address. Your best bet would be something like:
    Code:
    IP=127.0.0.1
    
    valid=1
    count=0
    
    for field in $(echo "$IP" | cut -d. --output-delimiter=$'\012' -f1-); do
        count=$[count+1]
        if [ "$field" -eq $[field+0] -a "$field" -le 256 -a "$field" -ge 0 ]; then
            : yay
        else
            valid=0
        fi
    done
    
    if [ "$valid" -a "$count" -eq 4 ]; then
        echo "Valid IP address!"
    else
        echo "Invalid IP address!"
    fi
    This uses cut to break the string into its '.'-separated parts, then employs the loop to ensure that each part is between 0 and 255 inclusive, and that there are exactly 4 parts.

    Make sense?
    DISTRO=Arch
    Registered Linux User #388732

  4. #4
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162
    Quote Originally Posted by Cabhan View Post
    First off, those appear to be different sorts of regular expressions. The first appears to be Perl syntax, while the second is a mix of POSIX and Extended POSIX.

    Your problem with the second is that Bash is taking the '{'s and '}'s away. Try escaping them on the commandline.

    For instance, using Perl regular expressions, this is the easiest way:
    Code:
    \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
    Using Extended POSIX regular expressions (enabled by using 'egrep' instead of 'grep'), you could do:
    Code:
    [:digit:]{1,3}\.[:digit:]{1,3}\.[:digit:]{1,3}\.[:digit:]{1,3}
    Having said all of this, there are a few problems. For instance, both of these would accept 300.1.1.1, which is obviously not a valid regular IP address. Your best bet would be something like:
    Code:
    IP=127.0.0.1
    
    valid=1
    count=0
    
    for field in $(echo "$IP" | cut -d. --output-delimiter=$'\012' -f1-); do
        count=$[count+1]
        if [ "$field" -eq $[field+0] -a "$field" -le 256 -a "$field" -ge 0 ]; then
            : yay
        else
            valid=0
        fi
    done
    
    if [ "$valid" -a "$count" -eq 4 ]; then
        echo "Valid IP address!"
    else
        echo "Invalid IP address!"
    fi
    This uses cut to break the string into its '.'-separated parts, then employs the loop to ensure that each part is between 0 and 255 inclusive, and that there are exactly 4 parts.

    Make sense?

    Well, I don't think I quite understand what that scripts function is, but matching invalid addresses like 300.1.1.1 or the like is okay for my purposes. I simply need to make a script that grabs each individual IP address from a log file. I didn't realize egrep was needed for the [::] type regular expressions, that's very useful information. however I still get an output like this

    Code:
    grep: [:digit:]1.[:digit:]1.[:digit:]1.[:digit:]3: No such file or directory
    grep: [:digit:]1.[:digit:]1.[:digit:]3.[:digit:]1: No such file or directory
    grep: [:digit:]1.[:digit:]1.[:digit:]3.[:digit:]3: No such file or directory
    grep: [:digit:]1.[:digit:]3.[:digit:]1.[:digit:]1: No such file or directory
    grep: [:digit:]1.[:digit:]3.[:digit:]1.[:digit:]3: No such file or directory
    grep: [:digit:]1.[:digit:]3.[:digit:]3.[:digit:]1: No such file or directory
    grep: [:digit:]1.[:digit:]3.[:digit:]3.[:digit:]3: No such file or directory
    grep: [:digit:]3.[:digit:]1.[:digit:]1.[:digit:]1: No such file or directory
    grep: [:digit:]3.[:digit:]1.[:digit:]1.[:digit:]3: No such file or directory
    grep: [:digit:]3.[:digit:]1.[:digit:]3.[:digit:]1: No such file or directory
    grep: [:digit:]3.[:digit:]1.[:digit:]3.[:digit:]3: No such file or directory
    grep: [:digit:]3.[:digit:]3.[:digit:]1.[:digit:]1: No such file or directory
    grep: [:digit:]3.[:digit:]3.[:digit:]1.[:digit:]3: No such file or directory
    grep: [:digit:]3.[:digit:]3.[:digit:]3.[:digit:]1: No such file or directory
    grep: [:digit:]3.[:digit:]3.[:digit:]3.[:digit:]3: No such file or directory
    Escaping the "{}" characters produced no errors however it did not match any of the IPs in the file. I'm running it on a test file with only two example IPs, the conent of which follows

    Code:
    68.112.34.23
    235.37.123.244

  5. #5
    drl
    drl is offline
    Linux Engineer drl's Avatar
    Join Date
    Apr 2006
    Location
    Saint Paul, MN, USA / CentOS, Debian, Solaris, SuSE
    Posts
    1,117
    Hi.

    Adding brackets around the digit expressions like this:
    Code:
    #!/bin/sh -
    
    # @(#) s1       Demonstrate egrep.
    
    cat >data1 <<'EOF'
    garbage with no digits
    68.112.34.23
    235.37.123.244
    frog
    EOF
    
    echo
    echo " Input file:"
    cat data1
    
    echo
    echo " Results from grep, expecting 2 lines:"
    egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' data1
    
    exit 0
    produces:
    Code:
    &#37; ./s1
    
     Input file:
    garbage with no digits
    68.112.34.23
    235.37.123.244
    frog
    
     Results from grep, expecting 2 lines:
    68.112.34.23
    235.37.123.244
    See man egrep for details ... cheers, drl
    Welcome - get the most out of the forum by reading forum basics and guidelines: click here.
    90% of questions can be answered by using man pages, Quick Search, Advanced Search, Google search, Wikipedia.
    We look forward to helping you with the challenge of the other 10%.
    ( Mn, 2.6.n, AMD-64 3000+, ASUS A8V Deluxe, 1 GB, SATA + IDE, Matrox G400 AGP )

  6. #6
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162
    Quote Originally Posted by drl View Post
    Hi.

    Adding brackets around the digit expressions like this:
    Code:
    #!/bin/sh -
    
    # @(#) s1       Demonstrate egrep.
    
    cat >data1 <<'EOF'
    garbage with no digits
    68.112.34.23
    235.37.123.244
    frog
    EOF
    
    echo
    echo " Input file:"
    cat data1
    
    echo
    echo " Results from grep, expecting 2 lines:"
    egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' data1
    
    exit 0
    produces:
    Code:
    % ./s1
    
     Input file:
    garbage with no digits
    68.112.34.23
    235.37.123.244
    frog
    
     Results from grep, expecting 2 lines:
    68.112.34.23
    235.37.123.244
    See man egrep for details ... cheers, drl
    Youre modifcation worked prefectly, as you already know. Are there any more indepth guides in the subtler bits of using grep like this? On my machine, "man egrep" opens up the grep man page, which I've read quite a bit.

    Anyway, I think I'll search for that myself, thanks for the help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...