使用 =~ 進行字元串模式匹配
我在理解 bash 中與 =~ 匹配的字元串模式時遇到****問題。
我編寫了以下函式(不要驚慌——它只是在試驗,而不是 md5sum 的安全方法):
md5 () { [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; }
並用一些輸入對其進行了測試。這裡有一些參考:
md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste
如果控制和的源不包含文件名的兩個空格,那麼比較就變得不必要了。這就是觀察的來源,但比解決該問題的許多方法更有趣的是我的觀察:
我定義了一個控制變數,並用太短但匹配的字元串測試我的函式:
ok=b1eb0d822e8d841249e3d68eeb3068d3 for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done fine fine fine fine
這是可以預料的,也很好,因為它是函式的目的,忽略失去的“wp.laenderliste”的不匹配,因此甚至更長的不匹配。
現在,如果我附加不匹配的隨機內容,我當然希望出現錯誤並獲取它們:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done baarr baarr baarr baarr
正如預期的那樣。但是當只有一個,最後一個不匹配的字元時,看看會發生什麼:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done fine fine fine fine
是我,沒有意識到這應該如何工作(選擇被破壞),還是在 bash 的模式匹配中真的存在一個錯誤?
字元串中間的不匹配從計數 1 開始:
for i in 5 9 e ; do echo md5 wp.laenderliste ${ok//$i/_} ;done md5 wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 md5 wp.laenderliste b1eb0d822e8d84124_e3d68eeb3068d3 md5 wp.laenderliste b1_b0d822_8d841249_3d68__b3068d3 for i in 5 9 e ; do md5 wp.laenderliste ${ok//$i/_} ;done fine baarr baarr
bash 版本:
bash -version GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>
免責聲明:md5sum 僅對無意錯誤有用,對攻擊無效。我不鼓勵使用它。
這個問題不是尋找更好的解決方案或變通方法。它是關於**=~**運算符的,它是否應該這樣做,如果是,為什麼。
=~
in ([[ ]]
) 是一個正則表達式模式匹配(或者更確切地說,一個search,見下文)。這與=
(or==
) 不同,後者使用與文件名萬用字元相同的模式。特別是,正則表達式中的星號表示“前一個單元的零個或一個副本”,因此
abc*
表示ab
加上零個或多個c
s。在您的情況下,尾隨星號使函式參數的最後一個字元是可選的。在您的最後一個範例中,模式變為
...68d3G*
,並且由於G*
匹配空字元串,因此它匹配類似...68d3
. “任何字元串”的正則表達式是.*
,或“任何字元,任意次數”。請注意,正則表達式匹配在字元串中的任何位置搜尋匹配,它不需要是整個字元串。所以模式
cde
會在字元串中找到abcdefgh
。你可能想使用這樣的東西:
[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok
我們在這裡並不真正需要正則表達式匹配,因為
md5sum
無論如何都會輸出尾隨空格(加上文件名),我們可以在模式中使用它來檢查我們是否與完整模式匹配。所以給函式一個截斷的雜湊是不匹配的。