Bash

shell測試多行字元串是否在最後一行包含指定的模式

  • April 23, 2018

我想確定多行字元串是否以包含指定模式的行結尾。

這些程式碼失敗,不匹配。

s=`echo hello && echo world && echo OK`
[[ "$s" =~ 'OK$' ]] && echo match

bash3.2 或更高版本中,如果未啟用與 3.1 的兼容性(使用compat31選項 or BASH_COMPAT=3.1),則引用正則表達式運算符(不僅與任何引用運算符 ( , , , ) 一起使用,\而且與任何bash引用運算符 ( '...', "...", $'...', $"...") 一起使用)將刪除它們的特殊含義。

[[ $var =~ 'OK$' ]]

僅在包含OK$字面的字元串中匹配($匹配字面量$

[[ $var =~ OK$ ]]

匹配以結尾的字元串OK(即匹配字元串末尾$的 RE 運算符)。

這也適用於儲存在變數中的正則表達式或某些替換的結果。

[[ $var =~ $regexp ]]   # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string

請注意,它可能會變得很尷尬,因為您需要為 shell 語法引用一些字元(如空格、、、、、不匹配時的括號<>&例如,如果您想匹配正則.{3} <> [)}]&表達式(3 個字元後跟 a " <> ",a)}a &),您需要類似:

[[ $var =~ .{3}" <> "[}\)]\& ]]

如果不確定哪些字元需要引用,您可以隨時使用臨時變數。這也意味著它將使程式碼與bash31,zsh或兼容ksh93

pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here

這也是您可以使用系統正則表達式的非 POSIX 擴展運算符的唯一方法(不使用compat31選項(或))。BASH_COMPAT=3.1

例如,要\<在許多正則表達式引擎中被視為單詞邊界,您需要:

pattern='\<word\>'
[[ $var =~ $pattern ]]

正在做:

[[ $var =~ \<word\> ]]

不會bash將它們\視為 shell 引用運算符並在傳遞<word>給 regexp 庫之前將它們剝離。

請注意,在 ksh93 中情況要糟糕得多,其中:

[[ $var =~ "x.*$" ]]

例如將匹配 onwhatever-xa*但不匹配whatever-xfoo。上面的引用刪除了 to 的特殊含義*,但沒有刪除 to .nor $

zsh行為更簡單:引用不會改變那裡的正則表達式運算符的含義(如在 bash31 中),這使得行為更可預測(它也可以使用 PCRE 正則表達式而不是 ERE(帶有)set -o rematchpcre)。

yash沒有[[...]]構造,但它的[內置有一個=~運算符(也在zsh)。當然,[作為普通命令,引用不會影響正則表達式運算符的解釋方式。


另請注意,嚴格來說,您$s不包含 3 行,而是 2 個完整的行,後跟一個未終止的行。它包含hello\nworld\nOK. 在OK$擴展的正則表達式中,$運算符只會匹配字元串的末尾。

在 3-full-lines string中,例如hello\nworld\nOK\n(您將無法通過命令替換獲得它,因為命令替換會去除所有尾隨換行符), ,$之後將匹配\n,因此OK$不會匹配它。

zsh -o pcrematch但是,如果存在匹配項,則$匹配字元串末尾和字元串末尾換行符之前的匹配項,因為它沒有將標誌PCRE_DOLLAR_ENDONLY傳遞給pcre_compile. 這可能被視為一個壞主意,因為 shell 中的變數通常不包含尾隨換行符,當它們包含時,我們通常希望它們被視為 data

引用自:https://unix.stackexchange.com/questions/371664