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

2 つのユニットの情報は、ファイルに 1000 回以上出力されます。

私のアルゴリズムは次のとおりです。

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

短いバージョン: 必要な値を取得します。ある時点で両方の値が特定の値を超えている場合、テストは合格です。私もBashを使ってこれをやろうとしています

明確にするために編集:私が抱えている問題は、変数をifステートメントに出し入れすることです。私の解析と比較は問題ありませんが、最後の if にたどり着くと、値が存在しないのは、それらが由来する if - fi に対してローカルであるためです (または、場合によっては由来しません)。

編集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

2 に答える 2

2

あなたが質問を投稿した理由は、whileループ内に設定された変数がwhileループが終了すると消えるように見えるためだと思います。

これは、パイプラインの一部としてwhileループを実行すると、サブシェルで実行され、サブシェルが終了しても、親シェルの環境は変更されず、サブシェルで何が起こっても影響を受けないためです。

パイプラインではなくリダイレ​​クトまたはプロセス置換を使用して入力データを取得することで、bashでこれを回避できます。たとえば、これは機能しません。

cat inputfile | while read line; do
  case "$line" in
    foo*) output=$line ;;
  esac
done
echo "output=$output"

これは機能しますが:

while read line; do
  case "$line" in
    foo*) output=$line ;;
  esac
done < inputfile
echo "output=$output"

これが私が思いついたものです:

#!/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

そして私が得た出力:

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

本当に物をのような変数に格納したいのであればUNIT_5_MEM、できると思いますが、配列はよりクリーンに見えます。また、処理しているデータを見ないと、何を達成しようとしているのかを知るのが難しいawkので、答えから外しました。

于 2012-10-05T11:20:38.960 に答える
1

そのようなテキスト フィルタリングを行う簡単な方法を探している場合は、sedまたはを参照してください[awk][1]。後者は簡単に解析でき、何らかの状態を保存できます。

このようなものである可能性があります(現在テストされていません)

#!/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();
}
于 2012-10-05T10:45:28.773 に答える