bashでサブシェルを作成していますか? [コピー]

bashでサブシェルを作成していますか? [コピー]

誰かがこのスクリプトが私が期待する結果を生成しない理由を説明できますか?

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

パイプはそうです。たとえば、$BASHPIDwhileループの内側と外側から印刷したり、次のように直接確認したりできます。

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

関連情報