awk help

Andreas Perstinger andipersti at gmail.com
Tue Apr 18 17:40:15 UTC 2017


I think awk is the better tool for your task but you could still 
simplify your shell script a little bit:

>      hits_rpt="/etc/ipf_pool_hits_rpt" >      rm $hits_rpt>      touch $hits_rpt> > 
hits_new="/etc/ipf_pool.hits.yes">      rm $hits_new>      touch 
$hits_new> >      hits_no="/etc/ipf_pool.hits.no">      rm $hits_no> 
  touch $hits_no
Using the "truncate" command you could reduce these lines to

hits_rpt="/etc/ipf_pool_hits_rpt"
hits_new="/etc/ipf_pool.hits.yes"
hits_no="/etc/ipf_pool.hits.no"
truncate -s 0 $hits_rpt $hits_yes $hits_no

>      ippool -l -d -m probing_ips > $hits_rpt 2> /dev/null > >      for line in `cat $hits_rpt`; do> >        # drop the first 3 
rpt lines>        poollist_line="">        poollist_line=`echo -n $line 
| grep poollist`>        [ -n "${poollist_line}" ] && continue> > 
role_line="">        role_line=`echo -n $line | grep Role`>        [ -n 
"${role_line}" ] && continue> >        nodes_line=""> 
nodes_line=`echo -n $line | grep Nodes`>        [ -n "${nodes_line}" ] 
&& continue
Assuming that your file always contains the three unneeded lines at the 
beginning you could use the "tail" command to start at line 4. And I 
would also use a while-loop in combination with the "read" built-in 
function. Then you are able to process pairs of lines:

tail -n +4 $hits_rpt | while read line
do

>        in_line1=`echo -n $line | grep Address:`
>        [ -n "${in_line1}" ] && save_in_line1="${in_line1}"
> 
>        in_line2=`echo -n $line | grep Hits`
>        [ -n "${in_line2}" ] && save_in_line2="${in_line2}"
> 
>        if [ "${save_in_line1}" -a "${save_in_line2}" ]; then
>          build_line1=${save_in_line1##*:}
>          build_line1=${build_line1%%/*}
>          build_line1="${build_line1};"
>          build_line2=${save_in_line2##*Hits }
>          # So remove everything to the right of the word Bytes.
>          build_line2=${build_line2%%Bytes*}

Using sed instead of grep would simplify the extraction of the IP 
address and the number of hits:

     ip=$(echo $line | sed -e 's/ *Address: *\([^/]*\).*/\1/')
     read line
     hits=$(echo $line | sed -e 's/ *Hits *\([[:digit:]*]\).*/\1/')

>          if [ ${build_line2} -gt 0 ]; then
>            db_rec="$added_date  ${build_line1}"
>            echo "${db_rec}" >> $hits_new
>          fi
>          build_line="${build_line2}  ${build_line1}"
>          echo "${build_line}" >> $hits_no
>          in_line1=""
>          in_line2=""
>          save_in_line1=""
>          save_in_line2=""
>        else
>          continue
>        fi
>      done
>      exit 0

So the complete shell script would be:

#!/bin/sh

added_date="`date +%Y%m%d`"
hits_rpt="/etc/ipf_pool_hits_rpt"
hits_new="/etc/ipf_pool.hits.yes"
hits_no="/etc/ipf_pool.hits.no"
truncate -s 0 $hits_rpt $hits_yes $hits_no

ippool -l -d -m probing_ips > $hits_rpt 2> /dev/null

tail -n +4 $hits_rpt | while read line
do
     ip=$(echo $line | sed -e 's/ *Address: *\([^/]*\).*/\1/')
     read line
     hits=$(echo $line | sed -e 's/ *Hits *\([[:digit:]*]\).*/\1/')
     if [ "$hits" -gt 0 ]; then
         echo "$added_date  ${ip};" >> $hits_new
     fi
     echo "$hits  ${ip};" >> $hits_no
done
exit 0

Does this still take minutes to process your data?

Bye, Andreas


More information about the freebsd-questions mailing list