[Perl] 一個常見的正規表示式的錯誤寫法

作者:   發佈於:   #perl

在不同的職場裡面都已經看過好幾次了。總是會有人用正規表示式:

$s =~ /\Afoo|bar\z/

... 來意圖檢查 $s 是否為 "foo""bar"

但是這正規表示式能比對到字串不只兩個,而是無限多個。

正規表示式 \Afoo|bar\z 代表的是「所有以 foo 開頭的字串」與「所有以 bar 結尾的字串」兩集合的交集。而不是 {"foo","bar"} 這個只有兩個字串的集合。

要滿足原意圖,必須補上小括號,但不要把 \A\z 括入:

$s =~ /\A(foo|bar)\z/

一般來說我認為,若用了 | ,就要同時加上小括號來明確區分出範圍,不然很容易造成誤讀。如果是明確寫成:

$s =~ /(\Afoo|bar\z)/

也可真正顯示出作者意圖真的就是要測試 $s 是否是「以 foo 開頭的字串」或是「以 bar 結尾的字串」。

附帶一提,以測試 $s 是否等於某些特定值來說,改用 eq 加上 any 來寫或許更能正確地彰顯出作者意圖。

看是要用 List::Utilany:

use List::Util qw(any);

any { $s eq $_ } qw(foo bar)

或是 any Junction:

use Quantum::Superpositions qw(any);

$s eq any( qw(foo bar) )

都是不錯的,也不太容易不小心寫錯。