正規表現で文字列A~文字列Bの検索(入れ子あり)

このQ&Aのポイント
  • 正規表現を使用して、文字列A~文字列Bの間にあるテキストを検索する方法について教えてください。
  • 正規表現を再帰的に使用して、入れ子構造を持つカッコにマッチする方法を教えてください。
  • 文字列Aから文字列Bまでのテキストを抜き出すための正規表現のプログラム例を教えてください。
回答を見る
  • ベストアンサー

正規表現:対応する文字列A~文字列Bの検索(入れ子あり)

いつもお世話になります。 以下のように (??{}) というのを使うと正規表現を再帰することによって入れ子があっても対応するカッコにマッチできることが分かりました。 以下のプログラムでは < から対応する > までを抜いています。 #! perl # betweenBracket -- < から対応 > までを抜く # 全角ブランクで字下げを表現しています。 $re = qr/  <   [^<>]*   (?:    (??{$re})    [^<>]*   )*  > /x; while(<DATA>) {  chomp;  for (/$re/g) {   print "$_ ";  }  print "\n"; } __DATA__ I <love> you I <love> <you> <I <love> <you>> 実行結果: <love> <love> <you> <I <love> <you>> これですが、<、>のような1文字のカッコではなくて文字列による開始~終了でもできるでしょうか。 具体的に言うと &lt; から &gt; までと言う風にしたいです。 #! perl # betweenEntity -- &lt; から対応 &gt; までを抜く ・・・???・・・・ __DATA__ I &lt;love&gt; you I &lt;love&gt; &lt;you&gt; &lt;I &lt;love&gt; &lt;you&gt;&gt; 実行結果: &lt;love&gt; &lt;love&gt; &lt;you&gt; &lt;I &lt;love&gt; &lt;you&gt;&gt; よろしくお願いします!

  • Perl
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

$re = qr/&lt; (?(?=&lt;|&gt;)(??{$re})|.)* &gt;/x; でどうだろうか.

TYWalker
質問者

お礼

うおーーー #! perl # betweenEntities -- &lt; から対応 &gt; までを抜く # 全角ブランクで字下げを表現しています。 $re = qr/&lt; (?(?=&lt;|&gt;)(??{$re})|.)* &gt;/x; while(<DATA>) {  chomp;  for (/$re/g) {   print "△$_△";  }  print "\n"; } __DATA__ I &lt;love&gt; you I &lt;love&gt; &lt;you&gt; &lt;I &lt;love&gt; &lt;you&gt;&gt; => >betweenEntities.pl △&lt;love&gt;△ △&lt;love&gt;△△&lt;you&gt;△ △&lt;I &lt;love&gt; &lt;you&gt;&gt;△ できますね!!! ありがとうございます。 明日ゆっくり解析&テストしようと思います。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

一応書いておくと, もとの正規表現が $re = qr/< (?:[^<>]|(??{$re}))* >/x; と等価なので, 区切りが 2文字以上になったときに (?:[^<>]|(??{$re})) をどうするか, もっというと [^<>] をどう処理するかという問題に落とすことができます. これは「開始の区切りである < もしくは終了の区切りである >」のいずれでもないもの, ということなので, これを 2文字以上のときにどう書くかという問題に帰着されます. で, 結局これが (?=&lt;|&gt;) を使って表せるぞ, ということで. ああ, (?:[^<>]|(??{$re})) に合わせるなら (?(?!&lt;|&gt;).|(??{$re})) の方が近いかも. あと, 開く記号と閉じる記号がちゃんとマッチしない (より正確には「開く方が多い」) 場合にどうなるかは試していないのでわかりません.

TYWalker
質問者

お礼

ありがとうございます。 昨日は &lt; を『に、&gt;を』に合わせて『から』までで変換するスクリプトを掛けて帰宅したんですが、今朝教えていただいたパターンと同じ結果を返すことが分かりました。 アサーションですね! これは大きく応用できそうです。 どうもありがとうございます。

関連するQ&A

  • 正規表現で文字クラスの引き算

    お世話になります。 正規表現の文字クラスについてお聞きします。 0~6 の数字1字を [0-6] という風に指定しますが、 .NET 正規表現では、 この中から 3~5 は除く、というようなとき、 [0-6-[3-5]] と言う風に書けるようですが、 Perl では書けないようです。 (一応ラクダ本と perldoc perlre には当たりました) #! perl # regtest.pl -- 正規表現のテスト while(<DATA>) { chomp; print "$_ matches /[0-6-[3-5]/\n" if /[0-6-[3-4]/; } __DATA__ 0 1 2 3 4 5 6 7 8 9 のようなスクリプトを動かすと、 C:\test>regtest.pl 0 matches /[0-6-[3-5]/ 1 matches /[0-6-[3-5]/ 2 matches /[0-6-[3-5]/ 3 matches /[0-6-[3-5]/ 4 matches /[0-6-[3-5]/ 5 matches /[0-6-[3-5]/ 6 matches /[0-6-[3-5]/ のような結果が得られ、引き算が確かに聞いていません。 Perl と .NET 正規表現は互換ではないのでしょうか。 また、Perl でも同じことが書けるでしょうか。 よろしくご教示願います。

    • ベストアンサー
    • Perl
  • 正規表現の質問です。

    実行環境がなく困っています・・ Perlで以下の正規表現はマッチするでしょうか? if("EUC-JP" =~ m|EUC|i ) { print "match"; }

    • ベストアンサー
    • Perl
  • 正規表現の\Gの使い方

    正規表現の\Gの使い方で質問です。 ものの本によると、\Gをつけるとパターンマッチは前回の処理の続きから行われるとのこと。すると以下のようなコードなら、 ta tb tc td te となるべきと思われます。 ところが実際は ta ta ta ta ta 明らかに\Gは無視されて、毎回$testの先頭から処理が行われています。 どこに間違いがあるのでしょうか。 #! c:/perl/bin/perl $test='tatbtctdtetftg'; for($i=0;$i<5;$i++) { $test=~/(\Gt.)/; print $1."\n"; }

  • 正規表現の書き方に困っております。

    あるSQLのダンプを変換するプログラムをPerlで書いているのですが、 うまく正規表現が書けなくて困っております。 データの途中に,が有ると、うまくいきません。 ''の中に囲まれた,は無視するという正規表現を書きたいのです。 また、'''B'も正しく処理できれば、完璧です。 #!/usr/bin/perl use strict; use warnings; #my $a = qq{'A','B',1}; --> うまくいく  ['A']['B'][1] #my $a = qq{'A,','B',1}; --> うまくいかない ['A] ['] ['] my $a = qq{',','''B',1}; --> もっとうまくいかない ['][']['] if($a =~ /(.+?),(.+?),(.+?)/){ print "[$1]\n"; print "[$2]\n"; print "[$3]\n"; }else{ print "ERR!\n"; } exit; __END__

    • ベストアンサー
    • Perl
  • 正規表現で [ ] を探したい

    正規表現の説明のサイトなど、調べてみたのですが、分からなかったのでお聞きします。 現在下記のようなテキストデータがあります。 []は半角カッコです。 ************* : [かきこ] あいうえお ばびぶべぼ [まみむめもI らりるれろ かきくけこ : ************* OCR処理をしている為、カッコ"]"が"I"大文字半角のアイになっている箇所があります。 その間違いを捜し当てたいのですが、 [ I I ] I I の3パターンあると思うのですが、それぞれを探せる正規表現を教えていただけないでしょうか? どなたかご教授願います。

  • CGIで受け取った日本語文字列を正規表現で

    perlでcgiを作っています。 テキストボックスに入れてもらった文字列から正規表現で数字を抽出します。 以下のように、組むと "USA"のような半角英数はただしくマッチしますが、 "アメリカ"や"ドル"などはマッチしません。簡単に解決する方法をお教えください。 my $text = $in_data{'data_text'}; $text =~ tr/+/ /; $text =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg; $text =~ s/[<>"'&\r\n]//g; $text =~ s/&/&amp;/g; $text =~ s/</&lt;/g; $text =~ s/>/&gt;/g; $text =~ s/"/&quot;/g; $text =~ s/'/'/g; $text =~ s/\r\n/<br>/g; $text =~ s/\n/<br>/g; $text =~ s/\r/<br>/g; if ($text =~ /USA (\d+) dollars/){ print "USA $1\n"; } if ($text =~ /アメリカ (\d+\.\d+) ドル/){ print "アメリカ $1\n"; } exit;

    • ベストアンサー
    • Perl
  • 正規表現について

    いつもお世話になっております。 perlの正規表現で分からない事があります。 ご存知の方がいらっしゃれば、アドバイスを頂けますようよろしくお願い致します。 (質問内容) 以下のようなプログラムを実行した場合、matchが出力されてしまいます。 $aには、「、IS」を設定しているので、「真」と扱われないと思うのですが、何故、matchが出力されるのでしょうか? また、「偽」として処理をいしたい場合、 どのようにすればよろしいのでしょうか? #!/usr/bin/perl $a = "、IS"; $b = "AIS"; if ($a =~ $b){ print "match\n"; } else{ print "not match\n"; }

  • VBAで改行の入ったデータの正規表現について

    vbaで複数行のデータの一部を抜き出そうと思っています。 下記のようにすると、抜き出したデータの先頭に改行がついてしまいます。 何かいい方法はないでしょうか。 data = "start" & vbCrLf  & "ABC" & vbCrLf & "DEF" & vbCrLf & "GHI" & vbCrLf & "end" Set re = New RegExp re.Pattern = "start((.|\n)*?)end" re.MultiLine = True Set mc = re.Execute(data) For i = 0 To mc.Count - 1 MsgBox m.SubMatches(0) Next i 上記を実行すると vbCrLf  & "ABC" & vbCrLf & "DEF" & vbCrLf & "GHI" & vbCrLf となってしまいます。 ”ABC”から抜き出す場合、正規表現をどう書けばいいのでしょうか。 よろしくお願いします。

  • perlの正規表現

    はじめまして現在Perlでスクリプトを作成しています。 やりたいことは ・ユーザがコマンドラインより文字(ユーザID)を入力 ・その文字列が#getent passwdの結果にあるか無いかで処理を分ける です。 #getent passwd | grep hogehogeの結果は下記のとおりです。 hogehoge:x:1210:104:staff:/home/data/staff/hogehoge:/bin/bash これより先頭の[hogehoge]とユーザが入力したhogehogeが完全一致すれば問題ありません。 正規表現を調べましたが文字列での一致はあるのですが引数での文字列が調べることが出来ませんでした。 よろしくお願いします。 print "Enter User ID\n"; $id = <STDIN>; chomp($id); $cmd =`getent passwd | grep $id`; system($cmd); if ($cmd == ~ /^$id/) { print "There is not ID\n"; } else { print "Your ID is there\n"; }

  • use encodingによって正規表現の結果が変わる?

    お世話になります。 webシステムで、画面入力値のチェックをperlで行っているのですが、 今回、perlのバージョンアップ対応を行っており、ソース修正をしたところ、以下のような現象に悩まされて困っております。 (本当のソースはもっと長いのですが、以下の現象により入力チェックが正常に動作しないという点までは突き止めました。) バージョン perl v5.8.0 os Red Hat Linux release 9 現象 use encodingが指定されていると、正規表現の$が効かないようです。 ソースと実行結果1 #!/usr/bin/perl #use encoding "euc-jp"; if ('apple' =~ /e$/) { print ("match\n"); } else { print ("unmatch\n"); } このときは match と表示されます。 ソースと実行結果2 #!/usr/bin/perl use encoding "euc-jp"; if ('apple' =~ /e$/) { print ("match\n"); } else { print ("unmatch\n"); } このときは、unmatch と表示されます。 対処方法のヒントだけでも頂けると助かります。 (他の質問を検索してみましたが、同様なものを見つけることができませんでした。) もしかして、perlのバグなのでしょうか?

    • ベストアンサー
    • Perl

専門家に質問してみよう