0
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
4
  • Please be polite. It'll get you more response. Commented Oct 5, 2012 at 10:35
  • Sorry, Was writing that while listening to a report by a co-worker. No impoliteness intended. Commented Oct 5, 2012 at 10:38
  • Hm... wonder how your co-worker appreciated that :) Commented Oct 5, 2012 at 10:40
  • It wasn't really aimed at me anyway! Edited for clearer question. Commented Oct 5, 2012 at 10:41

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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();
}

1 Comment

I actually use awk to get all the info for a particular case. the file (325k~ lines) Covers about 10 cases. I'll add what I have.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.