Reputation: 2330
case 4.1
Info for unit 1 starts now
info1
info2
info3
info5 - the one I want
info6
info7
Info for unit 2 starts now
info1
info2
info3
info5 - the one I want
info6
info7
endcase 4.1
The info for the 2 units are printed out over 1000 times in the file.
My algorithm is as follows:
while read line
do
if line contains unit1
then current_unit=1
if line contains unit2
then current_unit2
if line contains info5
then
if current_unit = 1
then unit1_val = *the relevant info from this line*
elif current_unit = 2
then unit2_val = *the relevant info from this line*
if both unit1_val > 20 && unit2_val > 20
then pass
Short version: pull the values i need, if at some point both values are over a certain value, test passed. I'm also trying to do this using Bash
Edit for clarity: The problem that I', having is passing variables in and out of if statements. My parsing and comparisons are fine, however When i get to the last if, the values are not there, because they are local to the if - fi they come from (or dont come from, as the case may be)
edit 2:
if [[ $line == *"info5"* ]]
then
CURRENT_UNIT=5
fi
if [[ $line = *"info6"* ]]
then
CURRENT_UNIT=6
fi
if [[ $line =~ "text i want" ]]
then
if [[ $CURRENT_UNIT -eq 5 ]]
then
UNIT_5_MEM=$(awk '/Used heap/ { gsub(/M/, " "); print $4 }')
elif [[ $CURRENT_VC -eq 6 ]]
then UNIT_6_MEM=$(awk '/Used heap/ { gsub(/M/, " "); print $4 }')
fi
fi
if [[ $UNIT_5_MEM -gt 20 && $UNIT_6_MEM -gt 20 ]]
then
echo "Passed"
fi
Upvotes: 0
Views: 189
Reputation: 46896
I gather that the reason you posted the question is because variables set inside your while loop seem to disappear once the while loop finishes.
This is because when you execute the while loop as part of a pipeline, it runs in a subshell, and when the subshell exits, the environment of the parent shell remains unchanged, unaffected by whatever was happening in the subshell.
You can get around this in bash by getting your input data using redirection or process substitution rather than a pipeline. For example, this doesn't work:
cat inputfile | while read line; do
case "$line" in
foo*) output=$line ;;
esac
done
echo "output=$output"
Whereas this does work:
while read line; do
case "$line" in
foo*) output=$line ;;
esac
done < inputfile
echo "output=$output"
Here's what I came up with:
#!/bin/bash
declare -A output
while read line; do
case "$line" in
*unit*)
unit=$(awk '{print $4}' <<<"$line")
;;
info5*)
output[$unit]="$line"
echo "FOUND: unit=$unit, line=$line" >&2
;;
esac
done < inp1
echo "Output 1:"
printf "%s\n" "${output[@]}"
### Alternately:
echo "Output 2:"
for ((i=${#output[@]}; i > 0; i--)); do
echo "unit=$i, line=${output[$i]}"
done
And the output I got:
FOUND: unit=1, line=info5 - the one I want
FOUND: unit=2, line=info5 - the one I want
Output 1:
info5 - the one I want
info5 - the one I want
Output 2:
unit=2, line=info5 - the one I want
unit=1, line=info5 - the one I want
If you really want to store things to variables like UNIT_5_MEM
, I suppose you can, but arrays seem cleaner. Also, without seeing the data you're processing, it's difficult to know what you're trying to achieve with awk
, so I've left that out of my answer.
Upvotes: 2
Reputation: 41519
If you're looking for an easy way to do textual filtering like that, better take a look at sed
or [awk][1]
. The latter is capable of easy parsing, and storing some state.
Could be something like this (currently untested)
#!/bin/awk
BEGIN {
current_unit=0;
}
function check_values()
{
if(values[1]>20 && values[2]>20) {
print "PASS"
exit
}
}
/Info for unit \d starts now/ {
current_unit=$4;
}
/info5/ {
values[current_unit]=value;
check_values();
}
Upvotes: 1