Memoize

BasicWerk   EC Support   Technique   Facebook  

20140818231352_ruby_regex_assertion_and_mode

ruby_regex_assertion_and_mode

 

 

Perl や PCRE の正規表現に慣れてると、Ruby で躓きやすいのが行頭(^)行末($)アサーションの動作と、シングルラインモードは /s ではなく /m で表現する点だ。

 

整理しよう。

 

まずはサンプルを用意。

 
> str = IO.read "sample.csv"
> puts str
id,name,price,currency
1,item-A,2980,JPY
2,item-B,900,JPY
3,item-C,3980,JPY
4,item-D,1980,JPY
 

 

Ruby では、行頭(^)行末($) は常に、デフォで各行の行頭行末にマッチする。

 
> str.scan /^.+$/
=> ["id,name,price,currency", "1,item-A,2980,JPY", "2,item-B,900,JPY", 
    "3,item-C,3980,JPY", "4,item-D,1980,JPY"]
 

 

つまり文字列全体の先頭と末尾にマッチさせたければ \A と \Z を使う。

 
# おっと、でもこのマッチは失敗する
> str.scan /\A.+\Z/
=> []
 

 

なぜか?

「.」が改行にマッチしないからだ。

改行文字にも . をマッチさせるようにするには /m モードにする。

 
> str.scan /\A.+\Z/m
=> ["id,name,price,currency\n1,item-A,2980,JPY\n2,item-B,900,JPY\n3,item-C,3980,JPY\n4,item-D,1980,JPY\n"]
 

 

 

実はこれだけのシンプルなことなんだ。

「Perl/PCRE でいう...は、Ruby では...で」云々と覚えようとするからややこしくなる。

 

ちなみに Ruby にも /s モードがあるが、これは Perl/PCRE のシングルラインモードとは全然意味が違う。

Ruby の /s モードは「ソースファイルのエンコードが Shift_JIS 以外、かつ、外部から入力された文字列が Shift_JIS であった場合に

正規表現がマッチできるようにする」というもので、つまり「sjis モード」の s ということ。

 


© Shin Nakamura/BasicWerk 2014