ログファイルのエントリをカウントする小さなスクリプトを作成しようとしています。また、ループの完了後に使用しようとしている変数(USCOUNTER
)をインクリメントしています。
しかし、その瞬間、USCOUNTER
は実際の値ではなく0に見えます。私が間違っていることを知っていますか?ありがとう!
FILE=$1
tail -n10 mylog > $FILE
USCOUNTER=0
cat $FILE | while read line; do
country=$(echo "$line" | cut -d' ' -f1)
if [ "US" = "$country" ]; then
USCOUNTER=`expr $USCOUNTER + 1`
echo "US counter $USCOUNTER"
fi
done
echo "final $USCOUNTER"
以下を出力します:
US counter 1
US counter 2
US counter 3
..
final 0
サブシェルでUSCOUNTER
を使用しているため、メインシェルに変数が表示されません。
cat FILE | while ...
の代わりに、while ... done < $FILE
を実行します。この方法で、 パイプラインにあるループに変数を設定します。ループが終了した後に変数が消えるのはなぜですか?または、データをパイプで読み取れないのはなぜですか? :
while read country _; do
if [ "US" = "$country" ]; then
USCOUNTER=$(expr $USCOUNTER + 1)
echo "US counter $USCOUNTER"
fi
done < "$FILE"
また、 ``式を$()に置き換えました。
また、while read line; do country=$(echo "$line" | cut -d' ' -f1)
をwhile read country _
に置き換えました。これにより、while read var1 var2 ... varN
が残りのコンテンツを含むvar1
まで、$var2
が行の最初の単語、$varN
などを含むように言うことができます。
-r
with readを使用 。cut
を使用する必要はありません。純粋なbashソリューションを使用できます。read
に2番目の変数(_
)を渡して、追加の「フィールド」をキャッチします[[ ]]
よりも[ ]
を優先 。while read -r country _; do
if [[ $country = 'US' ]]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
ミニマリスト
counter=0
((counter++))
echo $counter
final 0
はサブ(シェル)プロセスで実行されており、そこで行われた変更は現在の(親)シェルに反映されないため、while loop
を取得しています。
正しいスクリプト:
while read -r country _; do
if [ "US" = "$country" ]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Whileループで同じ$ count変数を使用すると、問題が発生します。
@ fedorqui's answer (および他のいくつか)は、実際の質問に対する正確な答えです。サブシェルは確かに問題です。
しかし、それは私を別の問題に導きました:ファイルコンテンツをパイプしていませんでした...しかし、一連のパイプとgrepsの出力...
私のエラーサンプルコード:
count=0
cat /etc/hosts | head | while read line; do
((count++))
echo $count $line
done
echo $count
そして、このスレッドの助けと プロセス置換 のおかげで私の修正
count=0
while IFS= read -r line; do
((count++))
echo "$count $line"
done < <(cat /etc/hosts | head)
echo "$count"
USCOUNTER=$(grep -c "^US " "$FILE")
次の1行コマンドを使用して、フレーズの特異性を使用してLinuxで多くのファイル名を変更します。
find -type f -name '*.jpg' | rename 's/holiday/honeymoon/'
拡張子が「.jpg」のすべてのファイルについて、文字列「holiday」が含まれている場合は、「honeymoon」に置き換えます。たとえば、このコマンドはファイル名を「ourholiday001.jpg」から「ourhoneymoon001.jpg」に変更します。
この例では、findコマンドを使用して、拡張子が.jpg(-name '* .jpg')のファイルのリスト(-type f)を送信し、パイプ(|)で名前を変更する方法も示しています。 renameは、標準入力からファイルリストを読み取ります。
変数のインクリメントは次のように実行できます。
_my_counter=$[$_my_counter + 1]
列内のパターンの出現回数をカウントするには、grepを使用します。
grep -cE "^([^ ]* ){2}US"
-c
カウント
([^ ]* )
コロンを検出するには
{2}
コロン番号
US
あなたのパターン