14347


とりあえず、サクラエディタで使われてたonigumo 5.13.5とubuntuのperl
5.14.2で試してみましたが、どちらも『この正規表現はおかしい』とのエラーが出てしまいました。

以下のような文字列があった時に、後読み、先読みを含めた`(?<=\d)hoge(?=\d)`というキーワードで検索すると、『1hoge1』『3hoge2』中の『hoge』がhitします。

[code]

    1hoge1
    2hogeA
    3hoge2
    4hogeB
    Ahoge4
    BhogeC
    Choge5
    DhogeD
    Ehoge7
    
[/code]

ここまでは良いのですが、キーワードに`(?<=\d+)hoge(?=\d)`のように量指定子を加えると正規表現として正しくないと怒られてしまいます。  
『+』『*』『?』で試してみましたが、全てダメでした。

これは、環境依存によって発生しているのでしょうか？  
それとも、正規表現としてこの書き方を認めていないのでしょうか？  
新しいversionのperlやruby使えば認められる書き方なんでしょうか？

情報お待ちしております。よろしくお願いします。


CC BY-SA 3.0
2015-08-13T02:03:43.777
14346
2015-08-13T03:33:01.667
2383
question
正規表現
正規表現の後読み、先読み中に量指定子は使えませんか？


正規表現の実装によります。各種エンジンでlookbehindに量指定子が使えるかどうかは、次のドキュメントに簡潔にまとまっています。OnigumoおよびPerl5の実装では(今のところ)使えないということです。

<http://www.regular-expressions.info/lookaround.html#limitbehind>

(ここには挙げられていませんが、Gaucheの正規表現もlookbehindで量指定子が使えます)

少し込み入った話をすると、「正規表現」というのはひとつの決まった定義があるわけではないので、「正規表現でこれはできますか?」という質問は「どの正規表現」かを言わないと曖昧です。もともとの「正規表現」は形式言語の理論の用語で、それにはきちんとした定義がありますが、そこで扱われるのは繰り返し、連接、選択などごく限られた機能だけです。プログラミング言語に取り入れられてから、実用上便利なように様々な拡張機能が付加されてきました。プログラミング界で言語を越えた仕様としてはPOSIXで定められたものがありますが、それもかなり機能が限られています。現代的に様々な拡張機能(lookahead,
lookbehind
assertionを含む)をてんこ盛りにしたリッチな正規表現を広めたのはおそらくPerlの功績だと思います。Perlの正規表現がポピュラーになったので、その仕様に準じた正規表現の実装がいくつか登場しました。ただ、今でも設計方針の違いから独自に正規表現を実装することはあり、その際にどの機能をどういう仕様で採り入れるかは設計者の選択によります。


CC BY-SA 3.0
2015-08-13T03:01:29.307
14347
2015-08-13T03:01:29.307
5258
14346
answer


後読みはPOSIX標準ではカバーされていないのですべて各エンジンの拡張機能という扱いだと思います。なのでエンジンにより対応には差があり[正規表現技術入門](http://gihyo.jp/book/2015/978-4-7741-7270-5)によると

  * 固定長限定…Perl、Python
  * 長さの異なる固定長文字列の選択が可能…PCRE、Ruby(鬼雲)
  * 可変長だが上限あり…Java
  * 制限なし…Perl6、.NET

という状況です。

つまり新しいPerlでは使用可能ですが、Rubyはおそらく未対応です。


CC BY-SA 3.0
2015-08-13T03:03:42.047
14348
2015-08-13T03:03:42.047
5750
14346
answer


`(?...)` は拡張正規表現でありPOSIX標準化されていませんので注意が必要です。

普通の正規表現だと括弧の直後の `?` は繰り返す対象がないので構文エラーとなりますが  
Perlでそれを拡張正規表現に使いました。その他の言語はそれにならって 拡張正規表現を実装したのだと思います。

さらに、後読みについては、実装の難易度が高いようで、ソフトウェアによって制限があり固定長の正規表現のみ可としているものが多いです。

'(?<=\d)' は固定長ですが '(?<=\d+)' は可変長なのでサポートしていないのでしょう。  
また `|` も正しく動くか確認が必要だと思います。

わたしは試したことありませんが、Javaや.NET Framework では繰り返しが使えるそうです。


CC BY-SA 3.0
2015-08-13T03:33:01.667
14350
2015-08-13T03:33:01.667
5008
14346
answer