
次の反復に進むために特定の基準(A)を確認するループがあります。skip
()という関数を呼び出すと、continue
ループ(B)が表示されないため、子プロセスで呼び出されたように見えることに気づきました。さらに、eval
文字列に依存する提案された回避策は機能しません(C)。
# /usr/bin/bash env
skip()
{
echo "skipping : $1"
continue
}
skip_str="echo \"skipping : $var\"; continue"
while read -r var;
do
if [[ $var =~ ^bar$ ]];
then
# A
# echo "skipping : $var"
# continue
# B
# skip "$var" # continue: only meaningful in a `for', `while', or `until' loop
# C
eval "$skip_str"
fi
echo "processed: $var"
done < <(cat << EOF
foo
bar
qux
EOF
)
方法C:
$ source ./job-10.sh
processed: foo
skipping :
processed: qux
また見なさい:
PS1:後で必要< <
なく理由を教えてくれる人はいますか?<
done
PS2:while
したがって、タグが見つかりません。for
答え1
関数は同じプロセスで実行されますが、ループと構文が異なります。他のほとんどすべてのプログラミング言語では、break
関数内または関数を使用して外部ループに影響を与えることはできません。continue
しかし実際にはシェルでは指定されていない:
continue [n]
もしN指定されたら、継続ユーティリティは一番上に戻る必要があります。Nthにはfor、while、またはUntilループが含まれています。もしN指定しない、続行は次のように動作します。N1 と指定されます。 [...][...]囲むループがない場合、アクションは指定されません。
取得する内容はシェルによって異なります。
Bashはエラーを発生させ、以下を無視しますcontinue
。
$ bash -c 'f() { continue; }; for x in a b c; do f; echo $x; done; echo done'
environment: line 0: continue: only meaningful in a ‘for’, ‘while’, or ‘until’ loop
a
environment: line 0: continue: only meaningful in a ‘for’, ‘while’, or ‘until’ loop
b
environment: line 0: continue: only meaningful in a ‘for’, ‘while’, or ‘until’ loop
c
done
Kshはこれを静かに無視します。
$ ksh -c 'f() { continue; }; for x in a b c; do f; echo $x; done; echo done'
a
b
c
done
Dash、Yash、Zshは実際にこれを適用しますが:
$ dash -c 'f() { continue; }; for x in a b c; do f; echo $x; done; echo done'
done
同様の考慮事項が使用法に適用できると予想しましたが、eval
実際にはそうではありません。少なくとも私は殻の間に何の違いも見ることができません。
ほとんどしないでください。ちょうど書いてください:
while read -r var;
do
if [[ $var =~ ^bar$ ]];
then
echo "skipping '$var'"
continue
fi
echo "processed: $var"
done
答え2
問題は、関数が実行されたときにループ内になくなったことです。サブシェルにはありませんが、ループ内にもありません。関数に関する限り、これは別のコードスニペットなので、どこで呼び出されるのかわかりません。
その後、実行するとeval "$skip_str"
未定義の時間に$var
設定したため、値はありません。これは実際に期待どおりに機能するはずです。何の理由もなく非常に複雑で危険です(入力を100%制御しない場合)。skip_string
$var
#! /usr/bin/env bash
while read -r var;
do
skip_str="echo \"skipping : $var\"; continue"
if [[ $var =~ ^bar$ ]];
then
eval "$skip_str"
fi
echo "processed: $var"
done < <(cat << EOF
foo
bar
qux
EOF
)
それ…あまりきれいではありません。個人的には、私は関数を使ってテストし、テスト結果に対処します。このように:
#! /usr/bin/env bash
doTest(){
if [[ $1 =~ ^bar$ ]];
then
return 1
else
return 0
fi
}
while read -r var;
do
if doTest "$var"; then
echo "processed: $var"
else
echo "skipped: $var"
continue
fi
## Rest of your code here
done < <(cat << EOF
foo
bar
qux
EOF
)
あなたの目標が何であるかを説明してください。
< <
最後に、それ以降は必要ありdone
ません< <()
。次の<
一般的な入力リダイレクトです<()
。プロセスの交換これは、コマンドの出力をファイル名として処理できるトリックです。
そのような追加の操作を繰り返さないために関数を使用する場合は、関数echo "skipping $1"
にさらにロジックを移動してループがあるようにします。このような:協会