continue:僅在“for”、“while”或“until”循環中有意義
我有一個循環來檢查是否跳到下一次迭代(A)的某些標準。我意識到,如果我呼叫一個呼叫 的函式 (
skip
)continue
,就好像它在子程序中被呼叫,因為它看不到循環 (B)。此外,依賴於 -uating 字元串的建議解決方法也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
問題是當你的函式被執行時,它不再在循環中。它不在子外殼中,不,但它也不在任何循環內。就函式而言,它是一段獨立的程式碼,不知道從哪裡呼叫它。
然後,當您執行時
eval "$skip_str"
,沒有任何值,$var
因為您設置skip_string
了$var
未定義的時間。這實際上應該像您期望的那樣工作,它只是非常複雜且有風險(如果您不控制輸入 100%),無緣無故:#! /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 )
如果你解釋你的目標是什麼,我可能會給你更好的東西。
最後,你不需要
< <
afterdone
,你需要< <()
. 這<
是正常的輸入重定向,<()
稱為程序替換,是一種技巧,可讓您將命令的輸出視為文件名。如果您使用該函式只是為了避免重複諸如 之類的額外內容
echo "skipping $1"
,則可以簡單地將更多邏輯移動到該函式中,以便在那裡有一個循環。像這樣的東西:連結
該函式可以在同一個程序中執行,它只是在語法上與循環不同。在幾乎任何其他程式語言中,您也不能在函式內部使用
break
或continue
在函式內部影響其外部的循環。但實際上,在 shell 中,它是未指定的:
continue [n]
如果指定了n,則 continue 實用程序將返回到第n個封閉 for、while 或 until 循環的頂部。如果未指定n,則 continue 的行為就像將n指定為 1 一樣。
$$ … $$ $$ … $$ 如果沒有封閉循環,則行為未指定。
你得到什麼取決於外殼:
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
我確實希望類似的考慮也適用於 using
eval
,但似乎情況並非如此。至少我看不出貝殼之間有任何區別。總而言之,不要那樣做。把它寫出來:
while read -r var; do if [[ $var =~ ^bar$ ]]; then echo "skipping '$var'" continue fi echo "processed: $var" done