• ベストアンサー

正規表現の仕様について

"abcdefg"という文字列に対して、/a(bc|bcd)/ という正規表現で検索すると 秀丸エディタの正規表現検索では、"abcd"がマッチし、 スクリプト言語のrubyでは"abc"がマッチします。 これは使用している正規表現ライブラリで演算子'|'の評価の仕方が異なるのだと思うのですが、統一された仕様のようなものは存在しないのでしょうか? 他の正規表現ライブラリ間でもこのような細かな動作の違いというのは存在するのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.3

GNU Awk v3.1.8 (DFA 型) awk 'BEGIN { str = "abcdefg"; sub(/a(bc|bcd)/, "xxx", str); print str; } xxxefg Perl v5.12.3 (NFA 型) perl -e '$str = "abcdefg"; $str =~ s/a(bc|bcd)/xxx/; print "$str\n";' xxxdefg 私もあまり詳しくはありませんが、DFA 型では選択を同時並行的に進めて、最長のものがマッチするようです。AWK は DFA 型を採用している少ない例で、Perl, Python, Ruby 等は NFA 型になっています。

siffon9
質問者

お礼

ご回答ありがとうございました。 ご回答を拝見しまして、以前勉強の為にDFA型の正規表現エンジンを作成したこと思い出し試してみましたところ、確かにAWKと同じ結果になりました。 --- regexp : a(bc|bcd) string : abcdefg match : ^ ^ # aとdを指しています。 ---NFA状態遷移表 no.: chr goto 0 : "a" [1] 1 : "b" [2, 4] 2 : "c" [3] 3A : 4 : "c" [5] 5 : "d" [6] 6A : ---DFA NFAをDFAに変換 no.: NFA状態no. 0 : [0] 1 : [1] 2 : [2, 4] 3A : [3, 5] 4A : [6] ---DFA状態遷移表 no.: chr goto 0 : "a" 1 1 : "b" 2 2 : "c" 3 3A : "d" 4 4A : --- 仰るとおり、同時並行的に進めて最長のものがマッチするDFA状態遷移表が作成されました。 なるほど、DFA型とNFA型で動作が異なるのですね、参考になる情報ありがとうございました。 ただ秀丸エディタの正規表現ライブラリがDFA型かというとそうでは無いように思えますが、NFA型でも作り方によって動作というか結果が異なるのでしょうか。

その他の回答 (5)

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.6

GNU sed v4.2.1 (or v1.18) echo 'abcdefg' | sed 's/a\(bc\|bcd\)/xxx/' xxxefg sed は NFA 型に分類されていると思いますが、私の手元にある2つのバージョンの実行結果は DFN 型と同じになります。GNU 版は DFA 型を採用しているのか、あるいは NFA 型だが細かいところの違いがあるのか、どちらなんでしょうか。後者だとすれば秀丸と同じ状況?

siffon9
質問者

お礼

再びのご回答ありがとうございました。 正規表現エンジン種類について検索しましたところ「詳細正規表現」という書籍のサンプルページを見つけました。 http://books.google.co.jp/books?id=RJFJ2I-thlsC&pg=PA141 そこには正規表現エンジンの種類として、DFA型、従来型NFA、POSIX NFA等があり、従来型NFAか否かを見分ける方法として正にこの質問で書いた正規表現の例が書かれておりました。 'abcd'がマッチするものはDFA型か、POSIX NFAというタイプであるとのことです。 正規表現エンジンの型というヒントをいただいたおかげで回答にたどり着くことができました、本当にありがとうございました。

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.5

>私は演算子'|'の動作としては、rubyやpythonの動作が普通で秀丸エディタの動作が特異だと考えたのですが、その理解で良いのでしょうか? 「普通」「特異」とはなんぞやと言うことで変わってきます。 そもそも、正規表現は、ed エディタや grep コマンドなどが発祥なので、そういう観点からするとabcdにマッチするのが「普通」です(edやgrepだと /a\(bc\|bcd\)/ ですが)。 現在では正規表現が使われるのはプログラム中のことが多いと思う(個人的な推測)ので、そういう観点からするとabcにマッチするのが「普通」じゃないかなと思います。

siffon9
質問者

お礼

ご回答ありがとうございました。 私の当該文章の中で書いた「普通」「特異」という表現は適切ではありませんでした、あの文章は個人的な感覚として書いてしまいました。 何らかの統一された仕様があり、それに則っているか、否かと書いた方が適切だったと思います。 あと、申し訳ありません、頂いたご回答の中で判らない部分があります。 > 正規表現は、ed エディタや grep コマンドなどが発祥なので、そういう観点からするとabcdにマッチするのが「普通」 これはDFA型のエンジンを搭載しているものは、abcdにマッチするのが普通という意味と理解しました。 > 正規表現が使われるのはプログラム中のことが多いと思う(個人的な推測)ので、そういう観点からするとabcにマッチするのが「普通」 この意味合いがよくわかりません?(一応、私の個人的な感覚とも一致はしているのですが……) プログラムの式で使用される四則演算子の様に左結合していく(左の要素から評価する)のが普通と考えられるという理解で良いでしょうか?

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.4

べつに興味本位ならとめませんが、 /a(bc|bcd)/なんて解釈がわかれる構文書いてたらいつまでたっても上達しないですよ

siffon9
質問者

お礼

ご忠告ありがとうございます。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

どうなっているかが重要なのではなくどうしたいかです 条件が競合しているのであれば「どちらかがヒットする」で どちらがヒットしても文句はいえないでしょう。 たとえばabcdを優先して、dがなくてもヒットするなら /abcd*/ で十分ですね。(abcの後ろに0個以上のdがある) 今回の命題だと逆の条件はつけられないです abcから始まってabcがヒットしたらそれでおしまいなら abcdにはどうやってもヒットしません。 考えて書けばさほど問題になるケースではありません

siffon9
質問者

お礼

ご回答ありがとうございました > どうなっているかが重要なのではなくどうしたいかです 発端は望んだ検索ができなかったことによるのですが、この質問をさせていただいたのはあくまで興味というか素朴な疑問によるものです。 従いまして、この質問においては「どうなっているか」に重点がありますことお汲み取りいただけますと幸いです。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

http://www.kt.rim.or.jp/~kbk/regex/regex.html まったく統一されていません。

siffon9
質問者

お礼

ご回答ありがとうございました

siffon9
質問者

補足

申し訳ありません、質問の仕方が悪かった様ですので補足させていただきます。 ツールにより使用できる演算子が違うというのは存じ上げております。 質問の意図は同じ演算子でも動作が異なることがあるのは普通のことなのかということになります。 ご紹介いただいたリンク先を拝見しますと、演算子'|'は左右のどちらかにマッチしますと書かれております。 http://www.kt.rim.or.jp/~kbk/regex/regex.html#VBAR 質問に書いた正規表現で'|'の左右の文字を逆にすると、秀丸エディタでは結果が変わらず、rubyでは結果が変わります。 これは秀丸エディタの正規表現ライブラリでは、'|'の両側を評価してマッチする文字列の長い方を返す仕様だと理解しました。 一方rubyは'|'の左側を評価してマッチすれば右側は評価しないような仕様に見えます。 試しにpythonでも試しましたがrubyと同じ結果になりました。 私は演算子'|'の動作としては、rubyやpythonの動作が普通で秀丸エディタの動作が特異だと考えたのですが、その理解で良いのでしょうか? それともこのような細かい動作の違いまで各ツール毎に異なっているのでしょか?

関連するQ&A

  • (秀丸)正規表現で、""をマッチさせるには?

    お世話になります。 以下2行に、それぞれマッチさせて、 末尾の""(ダブルコーティション)を外して置換えしたいです。 1-234,漢字,ABC,123円,"789" 1-234,漢字,ABC,"1,234円","789" 秀丸の正規表現 検索  ^(([^,]?)*),(([^,]?)*),(([^,]?)*),(([^,]?)*),"((.?)*)"$ 置換  \1,\2,\3,\4,\5 で試したところ、 1-234,漢字,ABC,123円,"789" では、マッチして、 1-234,漢字,ABC,123円,789 と置換されて結果OKでした。 しかし、 1-234,漢字,ABC,"1,234円","789" の方ではマッチしませんでした。 そこで質問させていただきますが、 1-234,漢字,ABC,"1,234円","789" でマッチするようにする為には、 上記しました秀丸の正規表現(検索)を、 どのように変更すればよろしかったでしょうか? 以上になります。 宜しくお願いいたします。

  • (?:系の正規表現

    perlの正規表現で以下の意味は、ABC01かABC99のみマッチするということでよいでしょうか? /^ABC(?:01|99)$/ (?:は$1など使用しない場合に用いるで正しいでしょうか? (?系の正規表現について知識不足ですが、一覧や詳しい書籍がありましたら教えてください。 昔、 /^ABC01|99$/ とかいて、ABC99がマッチせず、99がマッチしたので、|を使うときは、()を書いたのですが$1など変に作用させたくなかったので、最近(?:系の存在を知ってもっと詳しく知りたくなりました。 (?:はPerlの正規表現特有のものでしょうか?

    • ベストアンサー
    • Perl
  • (秀丸)正規表現で、特定文字列含む<~>範囲を選択

    お世話になります。 (秀丸の)正規表現について教えてください。 たとえば、テキストファイルに、1行、 ”<abc>文字列1です><abc>文字列2です><abc>文字列3です>(ここで改行)” という文字列が存在しています。 それを対象として、 (秀丸の)正規表現を利用し、 ”<abc>文字列2です>”だけをマッチさせたいのですが、 試しに、(秀丸の)正規表現で、 <abc.*文字列2.*?>  ←(なお、実際の記号は半角(.*?等)で、それぞれ入力しています・・・) で検索実行したところ、 ”<abc>文字列1です><abc>文字列2です>” として、 前の方に、マッチして欲しくない、 ”<abc>文字列1です>” までがマッチしてしまっている状況です。 そこでご質問なのですが、 上記におきまして、(秀丸の)正規表現を利用して、 ”<abc>文字列2です>”だけをマッチさせるには、 どのようにすれば、よろしかったでしょうか? (ちなみに秀丸は、2013年12月10日(火)現在の  最新バージョンVer8.32を利用しています) 以上になります。 宜しくお願いいたします。

  • 秀丸の正規表現

    秀丸の正規表現 http://pc.dearie.jp/hidemaru/replace/14.html 上記URLでメールの正規表現について解説があります。 [A-Za-z0-9\-\.\_]+@[A-Za-z0-9\-\_]+\.[A-Za-z0-9\-\.\_]+ この正規表現でメールの検索をおこなっています。この正規表現は理解出来ます。 .*([a-z0-9\-\.\_]+@[a-z0-9\-\_]+\.[a-z0-9\-\.\_]+)([^a-z0-9@\.\-\_]+).* キャプチャを使って正規表現でメールアドレスをマッチしているのは理解できます。 なぜ置換で、「\1,」とやっても、メールアドレスのみを取得できないのでしょうか? 実際に秀丸エディタを使ってやってみましたが、メールアドレスのみ取得することができませんでした。 検索ではメールアドレスにマッチするのに、なんでキャプチャが正しく動かないのかがわかりません・・・

  • ruby 正規表現

    こんばんは。 Rubyでの正規表現での質問なのですが、 例えば"hoge"という文字が含まれる行全体にマッチさせるような正規表現は存在するのでしょうか? また存在する場合はどのように記述すれば良いのでしょうか。 単純な質問で申し訳ありませんが、よろしくお願いいたします。

  • 正規表現ですが・・・

    正規表現なんですが(Perlです。) Aa_abcd_aa.txt Aa_abcd_bb.txt Aa_abcd_cc.txt Bb_abcd.txt 上記のabcdの部分をマッチさせるために (?<=Aa_|Bb_).*(?=_aa|_bb|_cc|\.txt) としてみましたが、これでは Aa_abcd_aa.txt Aa_abcd_bb.txt Aa_abcd_cc.txt のabcd_aaやabcd_bbやabcd_ccとマッチしてしまいます。 なにかよい表現の仕方はありますか? まとめてマッチさせる表現が知りたいです。

  • 「マッチしない」正規表現の書き方

    正規表現について、おたずねします。 文字列 abc,def,ghi のいずれかにマッチする正規表現は (abc|def|ghi) ですよね。 それでは、「abc,def,ghi のいずれにもマッチしない」正規表現は、どう書けばいいのでしょうか? あちこち調べましたが、どうしてもわかりません。 ただし、if $a =~ /(abc|def|ghi)/ などで、=~ を !~ に直す、というのはナシです。あくまでも右辺の式の中で表現したいのですが…

  • 秀丸で正規表現を使って置換

    あるファイルに関して、このような置換を行いたいです。 abc/xxx,yyy,zzz.html ↓ abc/xxx.html xxxとyyyとzzzはある任意の文字列(英数字で文字数はばらばら)で 「abc/」と「,」と「.html」は固定の文字列になります。 そこで、秀丸で開いて、正規表現による検索で、 「abc/.*,.*,.*.html」 として検索すると、該当部分が検索できることがわかりましたが、置換後をどのように設定すればいいのかわかりません。 置換後のabc/xxx.htmlの「xxx.html」の部分は検索前の任意の文字列をそのまま残したいのです。 秀丸の置換機能でこのようなことは可能でしょうか? 正規表現に関してあまり詳しくないので教えてください。

  • 正規表現について

    /^R|ruby$/ 上記のような正規表現があったとします。 この正規表現の【|】の判断がわかりません。具体的には、/^ $/という記述から 対象の文字列の先頭がRかrのどちらかで以降がubyと続く文字列にマッチという 意味だと解釈しているのですが違うのでしょうか? 具体的にはRubyという文字列かrubyという文字列の二つのうちどちらかにしか マッチしないとおもっていたのですが、 rrubyという文字列やRrubyという文字列にもマッチします。そもそもこの場合のR|rの箇所ですが、これはRかrのどちらかが先頭にあり 二文字目からはubyという文字列がつづきますよ。という正規表現ではないのでしょうか? かなりこまっています。 識者のかたご教授ください。

  • 秀丸の正規表現はどの流派に属しているのですか?

    秀丸エディタ64 (バージョン8.20)を使用しています。 秀丸の正規表現は、どういった流派(?)の流れを汲んでいるのでしょうか?よく、○○互換の正規表現という言葉がありますよね。Perl互換、.NET互換など、、、Java、C、そのほかの言語/プラットフォームで秀丸の正規表現に最も近いのは何でしょうか、教えてください。

専門家に質問してみよう