基於命令的 if 語句
我發現這種方式來執行
if
命令:$if echo test | grep st ; then echo yes ; fi ; echo $? test yes 0
看起來挺好的。讓我們嘗試一個不匹配:
$if echo test | grep 123 ; then echo yes ; fi ; echo $? 0
那是不對的。該
if
語句正常執行,但返回零退出程式碼。有人可以為我解釋一下嗎?
$?
塊之後if
包含if
語句的退出狀態。該標準規定命令的退出狀態
if
應為已執行的then
或else
複合列表的退出狀態,如果未執行,則為零。在第一種情況下,您會看到
echo yes
命令的退出狀態。then
第二種情況,在or塊中沒有執行任何命令else
,所以退出狀態為 0。
來自 bash 手冊(添加了格式和重點):
如果列表;然後列出;$$ elif list; then list; $$…$$ else list; $$是
if 列表被執行。如果其退出狀態為零,則執行 then 列表。否則,依次執行每個 elif 列表,如果其退出狀態為零,則執行相應的 then 列表並完成命令。否則,執行 else 列表(如果存在)。退出狀態是最後執行的命令的退出狀態,如果沒有條件測試為真,則為零。
因此,重要的部分是了解您實際查看的內容的退出狀態。在您的範例中,
echo test | grep 123
最後一個命令沒有成功退出。如果你先做了grep
然後測試了退出狀態,你會看到它返回非零退出狀態:$ grep 'noexist' /etc/passwd $ echo $? 1
相比之下,在 if 語句中,作為條件的命令沒有測試為真,因此根據規範和手冊 - 退出狀態為 0。
請注意,
grep '123'
如果您目前目錄中有文件 123,則未引用的模式可能是其他問題。關於 grep 和引用模式的旁注
Stephen Kitt 在評論中要求對最後一段進行詳細說明。這不一定與這個問題的主題相關,這裡已經提到過,我在這裡回答了類似的問題,但我會切線,因為這很有趣。讓我們看兩個例子。
在這裡,我們有一個
grep input
簡單的不帶引號的字元串。grep
的語法是這樣的,它會將第一個字元串視為模式。這裡沒問題,這有效:bash-4.3$ strace -e trace=execve grep input <<< "this is input line" execve("/bin/grep", ["grep", "input"], [/* 80 vars */]) = 0 this is input line +++ exited with 0 +++
但是,看看當你有(你認為是)正則表達式時會發生什麼。
bash-4.3$ strace -e trace=execve grep input* <<< "this is input line" execve("/bin/grep", ["grep", "input.txt", "input.txt.bak"], [/* 80 vars */]) = 0 +++ exited with 1 +++
shell 看到了你
*
並執行了路徑名擴展。現在 shell 執行的實際命令是grep some_file_1 some_file_2 some_file_3
,並且按照grep
語法grep [OPTIONS] PATTERN [FILE...]
- 該命令現在將input.txt
在裡面查找字元串input.txt.bak
。其實看看這個:bash-4.3$ echo "I have input.txt here" > input.txt.bak bash-4.3$ grep input* <<< "this is input line" I have input.txt here
輸入字元串被完全忽略,
grep
只搜尋擴展的文件名,你得到了你不想要的結果。