Hatena::Grouprubyist

Rubyをラクガク(正規表現編) RSSフィード

2009-12-16

[] 最短一致: *?  最短一致: *? - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  最短一致: *? - Rubyをラクガク(正規表現編)  最短一致: *? - Rubyをラクガク(正規表現編) のブックマークコメント

*?

量指定子(quantifiers)。直前の表現の 0 回以上の繰り返し (最短一致)

正規表現
irb(main):015:0> puts "/'(.*)'/ =~ 'hoge''foo''bar': #{/'(.*)'/ =~ "'hoge''foo''bar'"}" /'(.*)'/ =~ 'hoge''foo''bar': 0
=> nil
irb(main):016:0> $1
=> "hoge''foo''bar"
irb(main):017:0> puts "/'(.*?)'/ =~ 'hoge''foo''bar': #{/'(.*?)'/ =~ "'hoge''foo''bar'"}" /'(.*?)'/ =~ 'hoge''foo''bar': 0
=> nil
irb(main):018:0> $1
=> "hoge"

正規表現初心者は、最短一致の方が直感的に理解しやすいと思う。

2009-12-14

[]アトミック、強欲 アトミック、強欲 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク - アトミック、強欲 - Rubyをラクガク(正規表現編) アトミック、強欲 - Rubyをラクガク(正規表現編) のブックマークコメント

(?> )

バックトラックを抑止する。

この表現はまだ試験実装中です。将来なくなる可能性もありますので、そのつもりで使ってください。特に汎用ライブラリなどで使ってはいけません。

正規表現

アトミック、強欲等、様々な呼び方があるが、要はバックトラックを抑止されてしまう。

> hoge = "hoge 'foo' 'foo' bar"
> hoge =~ /(?>'.*')\s'foo' bar/ #アトミック。「(?>'.*')が、「'foo' 'foo'」にマッチし、それ以降は「'foo' bar」にマッチできなくなってしまう。
=> nil
> hoge =~ /'.*'\s'foo' bar/ #欲張り。初回は「'foo' 'foo'」にマッチするが、それ以降の「'foo'」に対応できる文字列は見つからないので、バックトラック。
=> 5

2009-11-28

[]先読み 先読み - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク - 先読み - Rubyをラクガク(正規表現編) 先読み - Rubyをラクガク(正規表現編) のブックマークコメント

(?= )

先読み(lookahead)。パターンによる位置指定(幅を持たない)

正規表現

先読み、戻り読みは位置に対してマッチする。

puts "/(?=Jeffrey)Jeff/ =~ 'by Jeffrey fried1': #{/(?=Jeffrey)Jeff/ =~ 'by Jeffrey fried1'}"
puts "/(?=Jeffrey)Jeff/ =~ 'by Tomas Jefferson': #{/(?=Jeffrey)Jeff/ =~ 'Tomas Jefferson'}"
/(?=Jeffrey)Jeff/ =~ 'by Jeffrey fried1': 3
/(?=Jeffrey)Jeff/ =~ 'by Tomas Jefferson': 

[]戻り読み 戻り読み - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク - 戻り読み - Rubyをラクガク(正規表現編) 戻り読み - Rubyをラクガク(正規表現編) のブックマークコメント

(戻り読み(lookbehind)は Oniguruma *7が必要)

正規表現

ということで、1.9だと動作します。

ret = "its Jeffs pen.".gsub(/(?<=\sJeff)(?=s\s)/, "'")
puts "'its Jeffs pen.'.gsub(/(?<=\sJeff)(?=s\s)/, \"'\"): #{ret}"
ret = "its Jeffs pen.".gsub(/(?<!\sJeff)(?!s\s)/, "'")
puts "'its Jeffs pen.'.gsub(/(?<!\\sJeff)(?!s\\s)/, \"'\"): #{ret}"
'its Jeffs pen.'.gsub(/(?<=\sJeff)(?=s\s)/, "'"): its Jeff's pen.
'its Jeffs pen.'.gsub(/(?<!\sJeff)(?!s\s)/, "'"): 'i'ts' 'J'e'f'fs' 'p'e'n'.'

本当は「\s」ではなく「\b」で動かしたかったんだけど、うまく動作させることができなかった。

2009-11-23

[] キャプチャなしの括弧: (?:…)  キャプチャなしの括弧: (?:…) - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  キャプチャなしの括弧: (?:…) - Rubyをラクガク(正規表現編)  キャプチャなしの括弧: (?:…) - Rubyをラクガク(正規表現編) のブックマークコメント

(?: )

後方参照を伴わないグループ化。つまり、\1, \2 (あるいは、 $1, $2)などの対象にはならず、 単純なグループ化の用途で使用します。

正規表現

後方参照できない場合はnilが返る。

puts "/^([-+]?[0-9]+(\.[0-9]*)?)([CF])$/ =~ '12.34F': #{/^([-+]?[0-9]+(\.[0-9]*)\
?)([CF])$/ =~ '12.34F'}: #{$1}#{$2}#{$3}"

puts "/^([-+]?[0-9]+(?:\.[0-9]*)?)([CF])$/ =~ '12.34F': #{/^([-+]?[0-9]+(?:\.[0-\
9]*)?)([CF])$/ =~ '12.34F'}: #{$1}#{$2}#{$3}"
/^([-+]?[0-9]+(.[0-9]*)?)([CF])$/ =~ '12.34F': 0: 12.34.34F
/^([-+]?[0-9]+(?:.[0-9]*)?)([CF])$/ =~ '12.34F': 0: 12.34F

(?:…)を使わない方は$3まで、(?:…)を使う方は$2まで表示

2009-11-22

[] 背景  背景 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  背景 - Rubyをラクガク(正規表現編)  背景 - Rubyをラクガク(正規表現編) のブックマークコメント

正規表現の本を読んだものの、どうアウトプットするか困り果て、ここでRubyで淡々とおさらいをしていこうかと思い立った次第です。

詳説 正規表現 第3版

詳説 正規表現 第3版

[] 選択  選択 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  選択 - Rubyをラクガク(正規表現編)  選択 - Rubyをラクガク(正規表現編) のブックマークコメント

|

選択(alternative)。優先順位が低いので下の「グループ化」とあわせて使うことが多い。

正規表現
puts "/hoge|foo|bar/ =~ 'hoge': #{/hoge|foo|bar/ =~ 'hoge'}"
puts "/hoge|foo|bar/ =~ 'a foo': #{/hoge|foo|bar/ =~ 'a foo'}"
puts "/hoge|foo|bar/ =~ 'not found.': #{/hoge|foo|bar/ =~ 'not found.'}"
/hoge|foo|bar/ =~ 'hoge': 0
/hoge|foo|bar/ =~ 'a foo': 2
/hoge|foo|bar/ =~ 'not found.':

true/falseではなく、どこにマッチしたか位置が返ってくるのか。あまり戻り値をどう使うか気にしたことなかった。

[] 単語境界  単語境界 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  単語境界 - Rubyをラクガク(正規表現編)  単語境界 - Rubyをラクガク(正規表現編) のブックマークコメント

\b

文字クラス指定の外では語境界 (\w と \W のあいだにマッチ)。文字クラス指定内ではバックスペース (0x08)。

正規表現
puts "/\bhoge\b/ =~ 'foo bar hoge': #{/\bhoge\b/ =~ 'foo bar hoge'}"
puts "/\bhoge\b/ =~ 'foo hoge bar': #{/\bhoge\b/ =~ 'foo hoge bar'}"
puts "/\bhoge\b/ =~ 'hoge foo bar': #{/\bhoge\b/ =~ 'hoge foo bar'}"
puts "/\bほげ\b/ =~ 'ふー、ほげ、ばー': #{/\bほげ\b/ =~ 'ふー、ほげ、ばー'}"
puts "/\bほげ\b/ =~ 'ふー ほげ ばー': #{/\bほげ\b/ =~ 'ふー ほげ ばー'}"
hog/ =~ 'foo bar hoge': 8
hog/ =~ 'foo hoge bar': 4
hog/ =~ 'hoge foo bar': 0
ほ/ =~ 'ふー、ほげ、ばー':
ほ/ =~ 'ふー ほげ ばー':

一応日本語を試してみたけど、やっぱりNGだった(ruby-1.8.7p174)。「語境界 (\w と \W のあいだにマッチ)」なので、そうだよねー、という。

\w

英数字。[0-9A-Za-z_] と同じ。

正規表現

[] 量指定子の対象をグループ化  量指定子の対象をグループ化 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  量指定子の対象をグループ化 - Rubyをラクガク(正規表現編)  量指定子の対象をグループ化 - Rubyをラクガク(正規表現編) のブックマークコメント

「1.4.10 丸括弧と後方参照」にて、

これまで丸括弧(())の2つの使い方について見てきた。「|」の対象を制限する使い方と、疑問符(?)やスター(*)といった、量指定子の対象をグループ化する使い方である。

とあるが、「疑問符(?)やスター(*)といった」のスターの例を見た覚えが無かったのでやってみた。

puts "/hoge(foo)*bar/ =~ 'hogefoobar': #{/hoge(foo)*bar/ =~ 'hogefoobar'}"
puts "/hoge(foo)*bar/ =~ 'hogefoofoobar': #{/hoge(foo)*bar/ =~ 'hogefoofoobar'}"
puts "/hoge(foo)*bar/ =~ 'hogefoofobar': #{/hoge(foo)*bar/ =~ 'hogefoofobar'}"
puts "/hoge(foo)*bar/ =~ 'hogebar': #{/hoge(foo)*bar/ =~ 'hogebar'}"
/hoge(foo)*bar/ =~ 'hogefoobar': 0
/hoge(foo)*bar/ =~ 'hogefoofoobar': 0
/hoge(foo)*bar/ =~ 'hogefoofobar':
/hoge(foo)*bar/ =~ 'hogebar': 0

確かに*(スター)も対象をグループ化して使うことができる。

[] 後方参照  後方参照 - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク -  後方参照 - Rubyをラクガク(正規表現編)  後方参照 - Rubyをラクガク(正規表現編) のブックマークコメント

正規表現 \1 \2 ... \n は、後方参照です。n 番目の括弧(正規表現 ( ) グルーピング)にマッチした文字列にマッチします。

正規表現

置換する時にはよくお世話になっている後方参照をマッチのみで使用する。

puts "/(hoge)(foo)\1\2/ =~ 'hogefoohogefoo': #{/(hoge)(foo)\1\2/ =~ 'hogefoohoge\
foo'}"
puts "/(hoge)(foo)\1\2/ =~ 'hogefoo': #{/(hoge)(foo)\1\2/ =~ 'hogefoo'}"
puts "/(hoge)(foo)\1*\2*/ =~ 'hogefoo': #{/(hoge)(foo)\1*\2*/ =~ 'hogefoo'}"
puts "/(hoge)(foo)\1+\2+/ =~ 'hogefoohogefoo': #{/(hoge)(foo)\1+\2+/ =~ 'hogefoo\
hogehogehogefoofoo'}"
/(hoge)(foo)^A^B/ =~ 'hogefoohogefoo': 0
/(hoge)(foo)^A^B/ =~ 'hogefoo':
/(hoge)(foo)^A*^B*/ =~ 'hogefoo': 0
/(hoge)(foo)^A+^B+/ =~ 'hogefoohogefoo': 0

正規表現リテラルをキレイに書きたい。