作者:Seth Larson
譯者:豌豆花下貓@Python貓
英文:Regex character “$” doesn't mean “end-of-string”
轉載請保留作者及譯者資訊!
這篇文章寫一寫我最近在用 Python 的正規表示式模組(re
)開發 CPython 的 SBOM 工具時發現的一個令人驚訝的行為。
如果用過正規表示式,你可能知道 ^
表示 “字串開始”,並相應地將 $
視為 “字串結束”。因此認為, cat$
模式會匹配字串 "lolcat"
,但不會匹配 "internet cat video"
。
^
的行為讓我認為 $
也是類似的,但這並不一定成立,而且這種行為取決於不同程式語言及其寫法。
特別是對於 Python 來說,如果禁用了多行模式(這是預設設定),那麼,$
字元不僅可以匹配字串的末尾,還可以匹配字串末尾的換行符。
所以,如果你試圖匹配一個末尾沒有換行符的字串,在 Python 中使用 $
是做不到的!我本以為禁用多行模式後,就不會有這種匹配換行符的行為,但事實恰恰相反。
下一個合乎邏輯的問題是,如何在 Python 中匹配一個末尾不含換行符的字串?
在對 Python 和其它正規表示式語法進行多番研究後,我還發現了 \z
和 \Z
可以用於匹配 “字串結束” 字元。
在 Python 中,可以用 re.MULTILINE
來啟用多行模式,文件的描述如下:
當指定
re.MULTILINE
時,模式字元'$'
會匹配字串末尾以及每一行末尾(包含換行符)。預設情況下,'$' 只匹配字串末尾以及字串末尾的換行符之前(如果有的話)。
讓我們看看這些特性在不同平臺上是什麼表現:
模式匹配 "cat\n"? | "cat$" 多行模式 | "cat$" 無多行模式 | "cat\z" | "cat\Z" |
---|---|---|---|---|
PHP | ✅ | ✅ | ❌ | ✅ |
ECMAScript | ✅ | ❌ | ⚠️ | ⚠️ |
Python | ✅ | ✅ | ⚠️ | ❌ |
Golang | ✅ | ❌ | ❌ | ⚠️ |
Java 8 | ✅ | ✅ | ❌ | ✅ |
.NET 7.0 | ✅ | ✅ | ❌ | ✅ |
Rust | ✅ | ❌ | ❌ | ⚠️ |
- ✅: 模式與字串
"cat\n"
匹配 - ❌: 模式與字串
"cat\n"
不匹配 - ⚠️: 模式無效或不支援該用法
綜合上述表格,如果要匹配換行符,那麼在所有語言中使用多行模式的 $
,都能匹配成功;但如果不想匹配換行符,事情就會變得複雜起來。
如果不想匹配換行符,在除了 Python 和 ECMAScript 外的其它語言中,你可以使用 \z
。而在 Python 中,你需要使用 \Z
,在 ECMAScript 中使用非多行模式的 $
。
今天這些關於正規表示式的知識,你學會了麼?
注意:上述資料表的資訊收集自 regex101.com,我沒有用實際的程式設計環境進行測試。
以上是今天的分享,最後推薦一下我的《Python潮流週刊》專欄。這是一個專為國內 Python 開發者量身打造的資訊平臺,為你挑選最值得分享的文章、教程、開源專案、軟體工具、播客和影片、熱門話題等內容。
https://xiaobot.net/p/python_weekly?refer=2fc438e2-33fe-44bd-aa2f-ae7d8e782dea