2009-12-16
■ [正規表現] 最短一致: *?

*?
量指定子(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
■ [正規表現]アトミック、強欲

(?> )
バックトラックを抑止する。
この表現はまだ試験実装中です。将来なくなる可能性もありますので、そのつもりで使ってください。特に汎用ライブラリなどで使ってはいけません。
正規表現
アトミック、強欲等、様々な呼び方があるが、要はバックトラックを抑止されてしまう。
> 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
■ [正規表現]先読み

(?= )
先読み(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':
■ [正規表現]戻り読み

(戻り読み(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
■ [正規表現] キャプチャなしの括弧: (?:…)

(?: )
後方参照を伴わないグループ化。つまり、\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
2009-11-22
■ [正規表現] 背景

正規表現の本を読んだものの、どうアウトプットするか困り果て、ここでRubyで淡々とおさらいをしていこうかと思い立った次第です。
- 作者: Jeffrey E.F. Friedl,株式会社ロングテール,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/04/26
- メディア: 大型本
- 購入: 21人 クリック: 603回
- この商品を含むブログ (74件) を見る
■ [正規表現] 選択

選択(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.':
■ [正規表現] 単語境界

\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
正規表現
■ [正規表現] 量指定子の対象をグループ化

「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
確かに*(スター)も対象をグループ化して使うことができる。
■ [正規表現] 後方参照

正規表現 \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
正規表現リテラルをキレイに書きたい。