bash 腳本中的正規表示式

bash 腳本中的正規表示式

這是我第一次編寫 bash 腳本,所以我可能犯了一個簡單的錯誤。

基本上,我正在嘗試編寫一個腳本來獲取用戶的群組,如果他們位於某個群組中,它將相應地記錄下來。顯然會有更多的功能,但是當我甚至無法讓正規表示式工作時,建立這些功能就沒有意義了!

到目前為止,我有這個:

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

我嘗試過該正則表達式的每個地方,它都有效。但在 bash 腳本中,它只輸出$groups, 後跟No match.那麼有人可以告訴我這是怎麼回事嗎?

答案1

man 7 regex

括號表達式是用「[]」括起來的字元列表。 ……

...要包含文字“-”,請將其作為第一個或最後一個字元...。 [A]所有其他特殊字符,包括“\”,在括號表達式中都會失去其特殊意義。

嘗試使用egrep 進行正規表示式會出現錯誤:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

這是一個更簡單的版本,也給了一個錯誤:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

由於\並不特殊,所以這是一個範圍,就像[a-z]本來的那樣。你需要把你的放在-最後,例如[_-]或:

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

無論您的 libc 版本如何(在egrep或bash中),這都應該有效。

編輯:這實際上也取決於您的區域設定。線上說明頁確實警告了這一點:

範圍非常依賴整理順序,可移植程序應避免依賴它們。

例如:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

當然,即使它沒有錯誤,它也沒有做你想要的事情:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

它是一個範圍,在 ASCII 中包括\[^_

答案2

正規表示式的一般規則(以及較大程式碼段中的任何錯誤):逐步削減並重建它或使用二等分 - 任何對您更有效的方法。

在這種情況下,罪魁禍首竟然是下劃線——用反斜線轉義它就可以了。

相關內容