Reputation: 23
Trying to sort out an issue here. I have a file that includes many lines, but I want to filter for specific line, then compare two values within that line, and if the condition is met, I want to display said line. This would be done through the entire file. I'm looking to use a BASH script for this.
Format of line:
<timestamp> <date> : <ServerName> <Device> <In>/<Out> <Value1>/<Value2>
Example of line:
15:13:33 12/13/19 : Host1 Device1 In/Out 33/34
Using this, I want to do the following:
grep for "In/Out"
Separate 33 and 34 in variables
Compare 33 and 34
If delta between 33 and 34 is more than "X", display entire line to STDOUT.
So far, I have:
#!/bin/bash
input="logfile.log"
while IFS= read -r line
do
echo $line
done < "$input"
I understand where the echo $line
is, I could perform commands. But I'm not sure how to "echo" this and process it within the while loop.
I could do something like:
line=`grep "In/Out" logfile.log`
var1=`grep "In/Out" logfile.log | awk -F" " '{ print $7 }' | awk -F/ '{ print $1 }'`
var2=`grep "In/Out" logfile.log | awk -F" " '{ print $7 }' | awk -F/ '{ print $2 }'`
And then compare, the difference, and if met, echo the $line value, but that feels very inefficient.
Any thoughts/input would be greatly appreciated.
Upvotes: 0
Views: 664
Reputation: 204259
Assuming the answer you accepted does what you want, all you need is:
awk -F'[[:space:]/]+' '/In\/Out/ && ($NF - $(NF-1)) > 3' file
EDIT: given the sample input from your comment:
$ cat file
02:22:50 11/11/19 : Host1 Device1 In/Out 208/219
$ awk -F'[[:space:]/]+' '/In\/Out/ && ($NF - $(NF-1)) > 3' file
02:22:50 11/11/19 : Host1 Device1 In/Out 208/219
so if the script doesn't work for you then the most likely cause is you're using a pre-POSIX awk (e.g. nawk or a VERY old version of mawk) that doesn't support character classes. Given that, try hardcoding the blank and tab instead of [:space:]
:
$ awk -F'[ \t/]+' '/In\/Out/ && ($NF - $(NF-1)) > 3' file
02:22:50 11/11/19 : Host1 Device1 In/Out 208/219
Upvotes: 0
Reputation: 22042
Would you try the following:
X=3 # Or assign to whatever
pat="In/Out +([0-9]+)/([0-9]+)" # Regex pattern to extract the times
while IFS= read -r line; do
[[ $line =~ $pat ]] && (( ${BASH_REMATCH[2]} - ${BASH_REMATCH[1]} > X )) && echo "$line"
done < "logfile.log"
Test sample of logfile.log
:
15:13:33 12/13/19 : Host1 Device1 In/Out 33/34
15:13:33 12/13/19 : Host1 Device1 In/Out 33/36
15:13:33 12/13/19 : Host1 Device1 In/Out 33/38
15:13:33 12/13/19 : Host1 Device1 In/Out 33/40
Output:
15:13:33 12/13/19 : Host1 Device1 In/Out 33/38
15:13:33 12/13/19 : Host1 Device1 In/Out 33/40
[EDIT]
According to the OP's info, the regex pattern has been updated:
X=3
pat="In/Out +\(([0-9]+)/([0-9]+)"
while IFS= read -r line; do
[[ $line =~ $pat ]] && (( ${BASH_REMATCH[2]} - ${BASH_REMATCH[1]} > X )) && echo "$line"
done < "logfile.log"
Sample input:
15:13:33 12/13/19 : Host1 Device1 In/Out (33/34).
15:13:33 12/13/19 : Host1 Device1 In/Out (33/36).
15:13:33 12/13/19 : Host1 Device1 In/Out (33/38).
15:13:33 12/13/19 : Host1 Device1 In/Out (33/40).
Output:
15:13:33 12/13/19 : Host1 Device1 In/Out (33/38).
15:13:33 12/13/19 : Host1 Device1 In/Out (33/40).
The pattern In/Out +\(([0-9]+)/([0-9]+)
is composed of:
In/Out
... The literal string+
... One or more whitespace(s) (It may be illegible but there exists a whitespace before the plus sign.)\(
... A literal left paren([0-9]+)/([0-9]+)
... One or more digit(s) folowed by a slash and one
or more digits again. The surrounding parens generate capture groups
and the matched substrings (digits, in this case) are stored in the
bash variables ${BASH_REMATCH[1]}
and ${BASH_REMATCH[2]}
in order.Hope this helps.
Upvotes: 1
Reputation: 141583
Such (kind-of-)complicated operations on files are usually done in a single awk script.
awk -v X=10000 '
function abs(v) {return v < 0 ? -v : v}
{
if ($6 == "In/Out") {
split($7, a, "/");
if (abs(a[1] - a[2]) > X) {
print
}
}
}'
The script is almost human readable. First check if 6th field is In/Out
. If it is, split 7th field on /
, compute absolute value of the numbers and compare them with delta. If they compare "more than X", print the whole line.
Tested on repl. I think you will have to tweak the script to your needs.
Upvotes: 2