So I am going through a log file and extracting information from said log file such as device name, location, and time of log. It looks something like the following:
edge2.mco1-9 Jun 11:32:24 GMT %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success
I am coming across an issue where when I run the following:
for y in ${DeviceName[@]}
do
echo "Device: $y"
counter=1
for z in ${LocationName[@]}
do
testing=($(grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1))
if [[ ${testing[$counter]} =~ [^0-9] ]]
then
echo $z
echo $testing
fi
done
done
the day number is the only part outputted. DeviceName is an array of device names. LocationName is an array of location names. The complicated part was due to me wanting to only output the location name if it had something coming from the grep since I did not want a long list of locations that had no time attached to it. I did experiment with saving to a .txt file, which did do the correct time, but it seems outputting the correct time is more troublesome due to spaces. Using the example,
9 Jun 11:32:24 GMT
should be the output. Is there any way to get around this?
The $testing
is kept as attempts to do ${testing[$counter]}
, $(${testing[$counter]})
, and other methods did not work giving me errors. Errors are Jun
and ./finder: line 113: Jun: command not found
respectively $testing at least gives me the day number. Obviously there is an issue with spaces but I don't know how to fix this.
CodePudding user response:
Without a complete set of input data (eg, contents of DeviceName[]
and LocationName[]
arrays) we'll have to make some assumptions ...
From the given sample input line:
line='edge2.mco1-9 Jun 11:32:24 GMT %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success'
We'll pick the following values for the for
loop variables:
y=edge2
z=mco1
A modified grep
command:
$ grep "$y\.$z\-.*\%" <<< "${line}" | cut -f2 -d "-" | cut -f1 -d% | head -n 1
9 Jun 11:32:24 GMT
Loading this into the testing[]
array:
$ testing=( $(grep "$y\.$z\-.*\%" <<< "${line}" | cut -f2 -d "-" | cut -f1 -d% | head -n 1) )
$ typeset -p testing
declare -a testing=([0]="9" [1]="Jun" [2]="11:32:24" [3]="GMT")
Running the test:
$ counter=1
$ [[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
success
# turn on debugging to see what we're testing:
$ set -xv # turn on debugging
$ [[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
[[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
[[ Jun =~ [^0-9] ]] # contents of testing[1] == 'Jun'
echo success
success
$ set xv # turn off debugging
So far so good.
OP has stated the desired output should look like:
9 Jun 11:32:24 GMT
But the current echo
command has an issue:
echo $testing
$testing
is an array; without an index bash
treats $testing
the same as ${testing[0]}
which in this case outputs 9
(see the output from typeset -p testing
- above); to output the entire contents of the array OP can use:
$ echo "${testing[@]}"
9 Jun 11:32:24 GMT
Net result: OP should be able to change echo $testing
to echo "${testing[@]}"
to obtain the desired output.
OP has mentioned the code complication (loading testing[]
array, comparing testing[1]
???) is due to only wanting to print output if the grep
found a match.
We can streamline the code a bit by replacing the guts of the for z
loop with:
# no need for array, just capture datetime stamp:
dtstamp=$(grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1)
# is length of 'dtstamp' is non-zero?
if [[ -n "${dtstamp}" ]]
then
echo "${z}"
echo "${dtstamp}"
fi
If the objective is to only print ${z}
if the grep
finds a match (ie, OP doesn't need to print ${dtstamp}
) we can streamline the code a bit more to where the only command in the for z
loop is:
grep "$y\.$z\-.*\%" hacker.txt >/dev/null && echo "${z}"
Reviving my test code:
$ z=mco1
$ grep "$y\.$z\-.*\%" <<< "${line}" >/dev/null && echo "${z}"
mco1
$ z=xxxx
$ grep "$y\.$z\-.*\%" <<< "${line}" >/dev/null && echo "${z}"
<<<=== no output
NOTES:
- can also remove the
counter=1
from the current code - OP should consider cutting-n-pasting their code (along with the appropriate shebang, eg,
#!/bin/bash
) into shellcheck.net; this will report on syntax issues as well as make some suggestions re: 'best practices'