引言
Bash 是 Linux 系統下欽定的 shell。你可以通過
cat /etc/shells
查看當前系統支持的 shell 種類。
Bash 不但是系統管理員與內核交互的利器,且是一種語言,可以編寫大多數系統的自動化腳本,用于簡化運維工作。
今天我們學習一個知識點:如何在 Bash 中判斷某個字符串中,是否包含子字符串?

題外話
在高級編程語言中,一般都提供了該功能,比如 PHP 使用函數 strpos 查找子字符串首次出現的位置,有則返回 integer 整型,沒有則返回 false。
strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int
在 MySQL 中也經常使用字符串匹配,比如通配符 %,還可以使用函數 instr 來實現。
SELECT INSTR("abcd",'f');
問題的提出
一位開發者在編寫 Bash 腳本的過程中,遇到一個問題。首先是有這樣一個賦值操作:
string="My string"
然后他判斷是否存在某個子字符串:
if [ $string ?? 'foo' ]; then echo "It's there!"fi
他這里打的 ?? 是占位符號,不知道該怎么寫。甚至有了一種丑陋的寫法:
if echo "$string" | grep 'foo'; then echo "It's there!"fi
這樣的實現是不是 low 太多了?
解決方法
能用一行解決的問題,何必 BB!
一位開發者給出的方案是,如果判斷條件上使用了雙中括號,那么就可以這樣寫:
string='My long string'if [[ $string == *"My long"* ]]; then echo "It's there!"fi
注意,是將子字符串外部使用雙*號包裹。
其中 == 是字符串相等的比較符。而 * 則是通配符,會適配任意長度的任意字符。
強大的正則
我們知道,Bash 中的數據類型是極為弱的,不像高級語言那樣區分 integer, string, float, double, array, Object 等等。在 Bash 看來,萬物都是字符串。這與 Unix 的“一切皆文件”哲學不謀而合。
處理字符串,我們必然繞不開“正則表達式”。
上述的問題,有沒有可能使用強大的正則方式處理呢?答案是肯定的。
比如這樣寫:
string='My string';if [[ $string =~ "My" ]]then echo "It's there!"fi
注意我們使用了 =~ 用于正則匹配,而不是邏輯運算符了。
正如上面所述,Bash 中如果是數字的比較,也完全可以使用字符串的正則方式處理。
比如要判斷某個整數值,是否在某個有效的列表內。可以這樣寫。
number=3if [[ "1,3,5,6,9" =~ "${number}" ]]; then echo "Yes"fi
用起來是不是精簡多了。
知識延伸
像問題中使用 grep 用于子字符串篩選的那樣,其實有更穩固的寫法:
if grep -q foo <<
一般不使用 echo 后使用管道符 grep。
寫在最后
在命令行中敲一下測試測試吧。只有多實踐才能加深印象。
另外,正則表達式是真的強!
Happy coding :_)
我是 @程序員小助手 ,持續分享編程知識,歡迎關注。