141

ループを実行していて、COUNTER. カウンターが更新されない理由がわかりません。サブシェルが作成されたことが原因ですか?どうすればこれを潜在的に修正できますか?

#!/bin/bash

WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' |
(
while read WFY_URL
do
    echo $WFY_URL #Some more action
    COUNTER=$((COUNTER+1))
done
)

echo $COUNTER # output = 0
4

13 に答える 13

170

まず、カウンターを増やしていません。またはに変更COUNTER=$((COUNTER))すると増加します。COUNTER=$((COUNTER + 1))COUNTER=$[COUNTER + 1]

第二に、サブシェル変数を呼び出し先に逆伝播するのは難しいと思います。サブシェル内の変数は、サブシェルの外では使用できません。これらは、子プロセスにローカルな変数です。

これを解決する 1 つの方法は、中間値を格納するために一時ファイルを使用することです。

TEMPFILE=/tmp/$$.tmp
echo 0 > $TEMPFILE

# Loop goes here
  # Fetch the value and increase it
  COUNTER=$[$(cat $TEMPFILE) + 1]

  # Store the new value
  echo $COUNTER > $TEMPFILE

# Loop done, script done, delete the file
unlink $TEMPFILE
于 2012-05-09T12:30:31.163 に答える
93
COUNTER=1
while [ Your != "done" ]
do
     echo " $COUNTER "
     COUNTER=$[$COUNTER +1]
done

テスト済みのBASH:Centos、SuSE、RH

于 2012-10-18T19:17:53.897 に答える
17

使ってみて

COUNTER=$((COUNTER+1))

それ以外の

COUNTER=$((COUNTER))
于 2012-05-09T12:23:37.233 に答える
12

一時ファイルを使用する代わりに、whileプロセス置換を使用してループの周りにサブシェルを作成することを回避できます。

while ...
do
   ...
done < <(grep ...)

grep, grep, awk, awk, awkちなみに、これらすべてを1つに変換できるはずですawk

Bash 4.2以降、次のlastpipeオプションがあります。

現在のシェルコンテキストでパイプラインの最後のコマンドを実行します。ジョブ制御が有効になっている場合、lastpipeオプションは効果がありません。

bash -c 'echo foo | while read -r s; do c=3; done; echo "$c"'

bash -c 'shopt -s lastpipe; echo foo | while read -r s; do c=3; done; echo "$c"'
3
于 2012-05-09T13:59:04.353 に答える
12

grep|grep|awk|awkこの単一の awk 呼び出しはパイプラインと同等だと思います: テストしてください。最後の awk コマンドは、何も変更していないように見えます。

COUNTER の問題は、while ループがサブシェルで実行されているため、サブシェルが終了すると変数への変更が失われることです。同じサブシェルで COUNTER の値にアクセスする必要があります。または、@ DennisWilliamson のアドバイスに従い、プロセス置換を使用して、サブシェルを完全に回避します。

awk '
  /GET \/log_/ && /upstream timed out/ {
    split($0, a, ", ")
    split(a[2] FS a[4] FS $0, b)
    print "http://example.com" b[5] "&ip=" b[2] "&date=" b[7] "&time=" b[8] "&end=1"
  }
' | {
    while read WFY_URL
    do
        echo $WFY_URL #Some more action
        (( COUNTER++ ))
    done
    echo $COUNTER
}
于 2012-05-09T14:17:02.807 に答える
12
count=0   
base=1
(( count += base ))
于 2013-07-22T13:06:41.050 に答える
9

ミニマリスト

counter=0
((counter++))
echo $counter
于 2015-11-05T04:59:46.243 に答える
0

counterスクリプトを更新していないようです。counter++

于 2012-05-09T12:26:40.147 に答える