誰かがこのスクリプトが私が期待する結果を生成しない理由を説明できますか?
#!/bin/bash
#
var=0
ls -1 /tmp| while read file
do
echo $file
var=1
done
echo "var is $var"
ファイルのリストを取得してからvar is 0
varが1でない理由は何ですか? whileループがサブシェルを生成するためですか?
答え1
パイプはそうです。たとえば、$BASHPID
whileループの内側と外側から印刷したり、次のように直接確認したりできます。
ls | while read file; do
sleep 100;
done
、停止し、C-Z
後でターミナル セッションでプロセス ツリーを確認または表示ps
します。ps --forest
わずかに異なる「パイプライン」でサブシェルを防ぐことができます。
var=0
while read file
do
echo $file; var=1
done < <(ls -1 /tmp/)
echo $var #=> 1
答え2
他の良い答えは、すでに変数の値を保持していない理由を説明しました。必要に応じて、このトピックに関する興味深い記事を読むことができます。パイプライン内のループに変数を設定しました。ループが終わるとなぜ消えますか?それともパイプを介してデータを読み取れないのはなぜですか?。
ls
私は構文解析がまったく必要ないようにファイルを繰り返す別の方法を示したかったのです。
for file in /tmp/*
do
echo "$file"
var=1
done
それだけです!/tmp/*
Expandにディレクトリのすべての内容を提供するように依頼するだけです/tmp
。
あなたのスクリプトは実際のコードではなくダミーコードのようです。ただし、特定の値が含まれていることを確認したい場合は、/tmp
次のように言うこともできます。
shopt -s nullglob
r=(/tmp/*)
次に、配列の要素数を計算します。
echo ${#r[@]}
このパターンに一致するものがない場合は、リテラル文字列への拡張をブロックしshopt -s nullblog
ました。/tmp/*
/tmp/*
答え3
while
いいえ、しかしパイプはそうです。したがって、while
例はサブシェルで実行されます。
for
繰り返しリストを生成するコマンドは、ループではなくサブシェルで実行されるループを使用して同じ操作を実行できることがよくあります。たとえば、
for file in /tmp/*; do
echo "$file"
var=1
done