Groups | Search | Server Info | Keyboard shortcuts | Login | Register


Groups > tw.bbs.comp.lang.perl > #27

=?utf-8?B?5bi46KaL5Lq654K66Yyv6KqkOg==?= /\Afoo|bar\z/

From Kang-min Liu <gugod@gugod.org>
Newsgroups tw.bbs.comp.lang.perl
Subject =?utf-8?B?5bi46KaL5Lq654K66Yyv6KqkOg==?= /\Afoo|bar\z/
Date 2022-08-17 11:38 +0900
Organization Aioe.org NNTP Server
Message-ID <m1lernppbr.fsf@gugod.org> (permalink)

Show all headers | View raw


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

    $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::Util 的 any:

    use List::Util qw(any);

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

或是 any Junction:

    use Quantum::Superpositions qw(any);

    $s eq any( qw(foo bar) )

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

----

Back to tw.bbs.comp.lang.perl | Previous | Next | Find similar


Thread

=?utf-8?B?5bi46KaL5Lq654K66Yyv6KqkOg==?= /\Afoo|bar\z/ Kang-min Liu <gugod@gugod.org> - 2022-08-17 11:38 +0900

csiph-web