awk commands inside of a bash script


Results 1 to 6 of 6

Thread: awk commands inside of a bash script

  1. #1
    Join Date
    Jul 2002
    Location
    Chesapeake, VA
    Posts
    252

    Question awk commands inside of a bash script

    im pretty sure this is a remedial task for many of you but im having an issue with arrays from a shell script being accessed in an awk command. im pretty good with shell scripting but i am embarrassingly unfamiliar with awk. so here's the meat of the script...

    Code:
    masks=( "0.0.0.0" "0.0.0.1" "0.0.0.3" "0.0.0.7" "0.0.0.15" "0.0.0.31" "0.0.0.63" "0.0.0.127" \
    "0.0.0.255" "0.0.1.255" "0.0.3.255" "0.0.7.255" "0.0.15.255" "0.0.31.255" "0.0.63.255" "0.0.127.255" \
    "0.0.255.255" "0.1.255.255" "0.3.255.255" "0.7.255.255" "0.15.255.255" "0.31.255.255" "0.63.255.255" \
    "0.127.255.255" "0.255.255.255" "1.255.255.255" "3.255.255.255" "7.255.255.255" "15.255.255.255" \
    "31.255.255.255" "63.255.255.255" "127.255.255.255" "255.255.255.255" )
    
    bits=( "32" "31" "30" "29" "28" "27" "26" "25" "24" "23" "22" "21" "20" "19" "18" "17" "16" "15" \
    "14" "13" "12" "11" "10" "9" "8" "7" "6" "5" "4" "3" "2" "1" "0" )
    
    
    if [ $# -lt 3 ]
    then
            echo "Usage: $0 <Input File (Crump)> <Output File (Blacklist)> <Format (cisco|juniper)>"
    fi
    
    awk=`which awk`
    input=$1
    output=$2
    format=$3
    
    if [ $format = "cisco" ]
    then
            $awk -v null="" 'BEGIN { IFS=" "; IRS="\n"; OFS=" "; ORS="\n"; } { line=0; print "deny ip  " $2 " " $3 " " "any"; }' < $input > $output
    elif [ $format = "juniper" ]
    then
            $awk -v masks="$masks" -v bits="$bits" 'BEGIN { IFS=" "; IRS="\n"; OFS=" "; ORS="\n"; }
                    { line=0;
                    for (i=0; i<=31; i++ ) {
                            if($3 == "${masks[$i]}")
                            {
                                    break;
                            }
                    }
                    print "\t" $2 "/" ${bits[$x]};
                    }
            ' < $input > $output
    fi
    
    echo "DONE!"
    i am trying to take an input file of ip addresses and corresponding netmasks and put it into a format to be loaded onto a juniper switch. the result should look something like this.. x.x.x.x/netmask using the cidr notation. no matter what subnet is provided though, /32 always gets appended to the end of the ip even when it should be /16, /24, etc... also, the cisco part works fine so that doesnt need any attention.

    any ideas on what i'm doing wrong?

  2. #2
    Join Date
    May 2011
    Posts
    1
    Not sure how much of help this can be, but I find this alot easier....

    cat 1.txt | perl -e use Net::CIDR; print join("\n", Net::CIDR::range2cidr(<STDIN>));

    1.txt:
    192.168.0.1-192.168.0.100
    192.168.1.0-192.168.1.50

    You can also make it work with netmask, doc has examples:
    http://search.cpan.org/~mrsam/Net-CIDR-0.11/CIDR.pm

  3. #3
    Join Date
    Sep 1999
    Location
    Cambridge, UK
    Posts
    509
    And what is $x?

  4. #4
    Join Date
    Jul 2002
    Location
    Chesapeake, VA
    Posts
    252
    i was setting x=i inside the awk script to see if i could then use it in the print statement. after trying a few different things, i decided to post here and just edited the code to reflect what i had originally, apparently forgetting to remove the $x.

  5. #5
    Join Date
    Sep 1999
    Location
    Cambridge, UK
    Posts
    509
    Well I don't really understand awk (I only read the first half of "sed and awk") so I might be missing something here but I had to make some changes to get the script to run at all.

    For a start with the script as written I got the following error:
    Code:
    awk: cmd. line:8:                 print "\t" $2 "/" ${bits[$i]};
    awk: cmd. line:8:                                    ^ syntax error
    so I had to go away and read up on arrays and find that the thing to do was to split the list of masks and bits into an actual array.
    Code:
                    { line=0;
                    split(masks, maskarray);
                    split(bits, bitarray);
                    for (i=0; i<=31; i++ ) {
                            if($3 == maskarray[i])
                            {
                                    break;
                            }
                    }
                    print "\t" $2 "/" bitarray[i];
                    }
    On top of all that you declared the masks and bits lists as bash arrays but since awk is interpreting them as strings you can't just say
    Code:
    awk -v masks="$masks" bits="$bits"
    Instead you need to say
    Code:
    awk -v masks="${masks[*]}" -v bits="${bits[*]}"
    That's definitely enough awk for one day.

  6. #6
    Join Date
    Jul 2002
    Location
    Chesapeake, VA
    Posts
    252
    i knew there had to be a way to do what i wanted! in all of my googling i didnt come across that split function once, or how to initialize arrays for use inside of awk. after making your changes this seems to work! at least i was on the right track! thanks for your help!

Tags for this Thread

Posting Permissions

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