Optimizing bash loop

now, i have to search for a pattern within a particular time frame which the user will provide in the following format:

19/Jun/2018:07:04,21/Jun/2018:21:30

it is easy to get tempted to attempt this search with a variation of the following awk command:

awk '/19\/Jun\/2018:07:04/,/21\/Jun\/2018:21:30/' datafile

but i think it can be more efficient than that. can i do this without having to call external utilities like awk?

im writing this code in /bin/sh. i intend to use this script on different unix flavors which includes but certainly isnt limited to ubuntu, redhat, fedora, debian.

here is the code im using to try to get the time from the log that is the closest to the time specified by the user:

        echo "${AllEpochTimes}" | awk -F"," -v c=1 -v t=${GoBackTimeEndin} '{a[NR]=$c}END{
                asort(a);d=a[NR]-t;d=d<0?-d:d;v = a[NR]
                for(i=NR-1;i>=1;i--){
                        m=a-t;m=m<0?-m:m
                        if(m<d){
                        d=m;v=a
                 }
                }
                print v
                }'

AllEpochTimes - contains all the converted time stamps of the log. as you can imagine, if the log file is huge, the content of this variable will skyrocket in size.

You'll need to convertall times to (arithmetically) comparable numbers or strings, either epoch seconds, or e.g. "YYYYmmddHHMM" format.

Perhaps a function like this will help you:

awk '
function toYMD(tm) {
   split(tm, vals, "[/:]");
   vals[2] = (index("JanFebMarAprMayJunJulAugSepOctNovDec", vals[2]) - 1) / 3 + 1
   return sprintf("%04d%02d%02d%02d%02d%02d", vals[3], vals[2], vals[1], vals[4], vals[5], vals[6])
}

BEGIN { print toYMD("21/Jun/2018:03:46:54") } '
1 Like

You can use /bin/egrep or /bin/grep -E

$ /bin/egrep "19\/Jun\/2018:07:04|21\/Jun\/2018:21:30" datafile | /bin/egrep -v "^$"
41.27.21.19 - - [19/Jun/2018:07:04:28 +0000]
41.27.21.19 - - [21/Jun/2018:21:30:28 +0000]
$ /bin/egrep Murugesan datafile | /bin/egrep -v "^$"
$ Ret=$?
$ if [ $Ret -eq 0 ]
  then
    echo Pass result
  else
    echo Fail result
  fi
Fail result
$ /bin/grep -E "19\/Jun\/2018:07:04|21\/Jun\/2018:21:30" datafile | /bin/grep -E -v "^$"
41.27.21.19 - - [19/Jun/2018:07:04:28 +0000]
41.27.21.19 - - [21/Jun/2018:21:30:28 +0000]
$ 
1 Like