Shell-Script
如何檢查字元串是否包含破折號或灰燼中的子字元串?
這是我正在嘗試的內容:
#!/bin/sh contains() { if $(echo $1 | grep -c $2) ; then echo "0" # contains else echo "1" # not contains fi } myString=$1 mySubsting=$2 contains $myString '$mySubsting'
下面是一個執行範例:
# sh ./myScript abcdef bc ./myTest: line 3: 0: command not found 1
編輯:
最初的問題是:如何在 Bourne Shell 中檢查字元串是否包含子字元串?
這是我正在嘗試的內容:
#!/bin/sh if echo $1 | grep -q $2 then echo "0" else echo "1" fi
下面是一個執行範例:
$ sh ./myTest "$(systemctl status ntp)" "Active: active" grep: active: No such file or directory 1
如何正確檢查一個字元串是否包含另一個字元串?
Bourne shell 有一個結構。這與現代相同
sh
(這看起來更像您正在使用的,Bourne shell 不支持$(...)
;如果它是 Bourne shell,您會得到一個不同的錯誤):case $1 in *"$2"*) printf '"%s" is in "%s"\n' "$2" "$1" esac
如果您想使用
grep
,那將是:if printf '%s\n' "$1" | grep -Fqe "$2"; then printf '"%s" is in "%s"\n' "$2" "$1" fi
或者
if grep -Fqe "$2" << EOF $1 EOF then printf '"%s" is in "%s"\n' "$2" "$1" fi
但這只有在
$2
不包含換行符的情況下才能正常工作。在任何情況下,您都需要在大多數參數擴展周圍加上引號。唯一不需要它的地方是在
case $1
上面,但即使那樣case "$1"
也不會有害。關於您的程式碼的一些註釋:
- 您不能
echo
用於任意字元串。在這裡,取決於實現,對於like或echo
的值,它會失敗。$1``-n``foo\bar
- 不加引號的參數擴展在 shell 中具有非常特殊的含義。你不想那樣做。例如,嘗試使用like或
grep -c $2
的值。$2``*``root /etc/passwd
grep
without-F
用於正則表達式匹配。您需要-F
固定字元串(子字元串)搜尋(曾經是 withfgrep
),但如果$2
包含多行,則表示grep -F
要搜尋輸入中這些行的任何grep -F $'a\nb'
內容(將查找a
orb
,而不是$'a\nb'
字元串)。- 在中,如果以 開頭
grep -c $2
,則 的內容$2
將被視為一個選項-
。你想要grep -c -e "$2"
或grep -c -- "$2"
避免這種情況。- 您想使用退出狀態,而不是標準輸出來報告布爾條件。在帶有
exit
(exit 0
代表真,exit 1
(或任何非零數字,但避免值大於 120)代表假)的腳本中。對於函式,請return
改用。儘管腳本和函式都將返回上次執行命令的狀態。$(cmd)
擴展為cmd
(並且由於再次缺少引號而在此處經歷 split+glob)減去尾隨換行符的輸出。因此,如果cmd
輸出0\n
,則$(cmd)
擴展為0
。因此 running$(cmd)
會嘗試執行名為0
. 如果您想將輸出轉換為cmd
退出狀態(因此它可以用作布爾值),您需要(exit "$(cmd)")
. 這將啟動一個子shell,該子shell 以 的輸出cmd
作為其退出程式碼)。grep -c
計算出現次數。在這裡,您不需要完整計數,您只需要知道是否找到它(如果至少有一個匹配項)。因為grep -q
它在找到一個後停止搜尋,因此效率更高。grep
對於不支持 (standard) 選項的古老實現-q
,您可以使用fgrep -le "$2" > /dev/null
. 使用-l
,fgrep
在第一次匹配時也停止,但輸出文件名(我們在這里通過將輸出重定向到 丟棄/dev/null
)。