正規表現 最長マッチが、機能しない

このQ&Aのポイント
  • Windows XP(sp3) ActivePerlを使用しているとき、正規表現の最長マッチが機能しない場合があります。
  • 具体的には、正規表現置換の部分で問題が発生します。
  • この問題の解決策として、文字列の一部を置換する際に、パターンにマッチする部分を正確に指定する必要があります。
回答を見る
  • ベストアンサー

正規表現 最長マッチが、機能しない。

# 正規表現 最長マッチが、機能しない。 # # Windows XP(sp3) ActivePerl # # This is perl 5, version 12, subversion 3 (v5.12.3) built for MSWin32-x86-multi-thread # (with 9 registered patches, see perl -V for more detail) # # Copyright 1987-2010, Larry Wall # # Binary build 1204 [294330] provided by ActiveState http://www.ActiveState.com # Built Feb 9 2011 14:38:22 # use strict; use utf8; use Encode; my $doc = "(L)12×(H)34×(W)56\n"; $doc =~ s%(\([LHW]\)(\d+))([^×cm])%$1cm$3%ig; # ←この部分 print encode("cp932", $doc); {出力結果} (L)1cm2×(H)3cm4×(W)56cm

  • Perl
  • 回答数8
  • ありがとう数11

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

  • ベストアンサー
  • sholmes
  • ベストアンサー率81% (89/109)
回答No.8

条件が細かく変わり続けているので自信ありませんが・・・ 推測込みでまとめるとこういうかんじでしょうか 1, (L)12× の「ようなもの」が続くとき、末尾の一つには×がつかない 2, 末尾ひとつの「ようなもの」の直後に、「cm」がなかった場合だけ「cm」を付与したい http://ideone.com/7hrZH

hh77777
質問者

お礼

回答ありがとうございます。 これで、解決しました。

その他の回答 (7)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.7

use strict; use warnings; use utf8; use v5.12; while (<DATA>) { s/\([LHW]\)\d+\K$/ cm/m; print; } __END__ (L)12×(H)34×(W)56 (L)12×(H)34 (L)12

hh77777
質問者

お礼

回答ありがとうございます。 正規表現の¥Kの意味が、わかりません。 実は、¥nのととろは、どんな文字が、来るかわからないのです。 要するに、cmが、なければ、cmを、挿入したいのです。

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

「入力の\nの前に、cm が、ない場合にのみ、cm を、つけたい」なら s/(?<!cm)\n/cm$&/; のような感じでいいんじゃないかな. あるいは \n のかわりに $ を使うともっと簡単かも.

hh77777
質問者

お礼

回答ありがとうございます。 実は、¥nのととろは、どんな文字が、来るかわからないのです。 要するに、cmが、なければ、cmを、挿入したいのです。

  • sholmes
  • ベストアンサー率81% (89/109)
回答No.5

となると、多分意図されているのはこの辺でしょうか 改行直前に、こういったパターンがあった場合だけcmをつけるという・・・ http://ideone.com/8Kf91

hh77777
質問者

お礼

回答ありがとうございます。 実は、¥nのところに、cmが、なければ、cmを、挿入したいのです。 ¥nも¥n以外の文字であるかもしれません。

回答No.4

量指定子でマッチした次の正規表現でマッチしないと、一個づつ戻ってマッチできるか確認します。 正規表現エンジンの側に立って考えるとよくわかります。 以下、表示がずれるので空白2文字を全角空白にしていることに注意。 #!/usr/bin/perl use strict; use warnings; use utf8; use Encode; # 正規表現デバッグ use re 'debug'; # 話を簡単にするために、全角Xを英字のxにする、g と i 演算子を外す。()も外す my $doc = "(L)12x(H)34x(W)56\n"; $doc =~ s/\([LHW]\)\d+[^xcm]/AAA/; print encode("utf8", $doc); __END__ $ perl -w foo.pl # 正規表現 "\([LHW]\)\d+[^xcm]" がコンパイルされると以下のようになる。 Compiling REx "\([LHW]\)\d+[^xcm]" Final program:   1: EXACT <(> (3)   3: ANYOF[HLW][] (14)  14: EXACT <)> (16)  16: PLUS (18)  17:  DIGIT (0)  18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}] (29)  29: END (0) anchored "(" at 0 (checking anchored) minlen 5 Guessing start of match in sv for REx "\([LHW]\)\d+[^xcm]" against "(L)12x(H)34x(W)56%n" Found anchored substr "(" at offset 0... Guessed: match at offset 0 # 正規表現 "\([LHW]\)\d+[^xcm]" で 文字列 "(L)12x(H)34x(W)56%n" を解析 Matching REx "\([LHW]\)\d+[^xcm]" against "(L)12x(H)34x(W)56%n"   0 <> <(L)12x(H)3>     | 1:EXACT <(>(3) # ( にマッッチした   1 <(> <L)12x(H)34>    | 3:ANYOF[HLW][](14) # L にマッチした   2 <(L> <)12x(H)34x>    | 14:EXACT <)>(16) # ) にマッチした   3 <(L)> <12x(H)34x(>   | 16:PLUS(18) # 数字 2 文字にマッチした                  DIGIT can match 2 times out of 2147483647...   5 <(L)12> <x(H)34x(W)>  | 18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}](29)                   failed... # [^xcm]にマッチしなかった   4 <(L)1> <2x(H)34x(W>   | 18: ANYOF[\0-bd-ln-wy-\377][{unicode_all}](29) # 1文字戻したらマッチした   5 <(L)12> <x(H)34x(W)>  | 29: END(0) Match successful! AAAx(H)34x(W)56 Freeing REx: "\([LHW]\)\d+[^xcm]"

hh77777
質問者

お礼

詳しい解説、ありがとうございます。 正規表現デバッグは、よくわかりませんが、マッチさせるために、1文字戻すと、いうことですね。

  • t-okura
  • ベストアンサー率75% (253/335)
回答No.3

(\d+) が (12), (34), (56) にマッチすると、つぎの文字は×なので ([^×cm]) に一致しません。 なので、(\([LHW]\)(\d+))([^×cm]) に一致するのは先頭だと (L)12 になり、これが最長一致になります。 (\([LHW]\)(\d+))([^×cm]) の部分を (\([LHW]\)(\d+))(×|) にすれば期待するものになるのではないでしょうか。

hh77777
質問者

お礼

ご回答、ありがとうございます。 私が、期待した、結果は、(L)12×(H)34×(W)56cm\n です。 また、入力が、(L)12×(H)34\n なら、(L)12×(H)34cm\n に、 (L)12\n なら、(L)12cm\n に、なって、ほしいのです。(数字の部分の桁数は、可変です。) 入力の\nの前に、cm が、ない場合にのみ、cm を、つけたいのです。 もし、お分かりになれば、期待する結果になる正規表現を、教えてください。

  • sholmes
  • ベストアンサー率81% (89/109)
回答No.2

1, 12 に対して、 \d+ は マッチします 2, 但し、次に来る × と [^×cm] がマッチしないため、\d+ = 12 というケースは除外されます。 3, 1 に対して、 \d+ は マッチします 4, 次に来る 2 と [^×cm] もマッチします。 ということで、こちらが採用(?)されます。 ・・・というような、動作に至るイメージの事でいいでしょうか? あんまし正確では無いかもしれませんが、何で\d+が12にならないのかは表現できたかなと 最後の56に関しては、×ではなく\nなので、[^×cm]へマッチしますよね? 試しに\nを外してみてください

hh77777
質問者

お礼

Perlは、できるだけ、マッチさせようと、するのですね。 勉強になりました。ありがとうございます。 私が、期待した、結果は、(L)12×(H)34×(W)56cm\n です。 また、入力が、(L)12×(H)34\n なら、(L)12×(H)34cm\n に、 (L)12\n なら、(L)12cm\n に、なって、ほしいのです。(数字の部分の桁数は、可変です。) もし、お分かりになれば、期待する結果になる正規表現を、教えてください。

  • sholmes
  • ベストアンサー率81% (89/109)
回答No.1

最長マッチ自体は動いていると思いますよ http://ideone.com/LLDQ0 桁区切りのとこまでしかマッチしないのは、次の部分じゃないでしょうか [^×cm] ×cmという三文字1セットの否定ではなく、(×|c|m)の否定になっています。 2,4,6はこの何れにもマッチしないため、そこで区切られるという・・・

hh77777
質問者

お礼

>×cmという三文字1セットの否定ではなく、(×|c|m)の否定になっています。 はい、それは、わかっています。 (\d+) が、(12), (34), (56) に、マッチするはずです。 なぜか、(1), (3), (56) に、マッチしているため、cm が、それぞれに、挿入されています。 (56) だけは、正しいですけど。

関連するQ&A

  • 正規表現 \s が、\n に、ヒットする。

    # 正規表現 \s が、\n に、ヒットする。 # # Windows XP(sp3) ActivePerl # # This is perl 5, version 12, subversion 3 (v5.12.3) built for MSWin32-x86-multi-thread # (with 9 registered patches, see perl -V for more detail) # # Copyright 1987-2010, Larry Wall # # Binary build 1204 [294330] provided by ActiveState http://www.ActiveState.com # Built Feb 9 2011 14:38:22 # use strict; use warnings; use utf8; my $a = "\n\n"; $a =~ s/\s/aaaaa\n/ig; print $a; __END__ [出力結果] aaaaa aaaaa

    • ベストアンサー
    • Perl
  • ActivePerl UTF-16の変換

    Active PerlをWindows上で利用しています。 (This is perl, v5.8.7 built for MSWin32-x86-multi-thread) 今回、毎回UTF-16という文字コードで生成されるテキストデータを Perlスクリプトで処理させたいのですが、sjis等への文字変換を スクリプト内で行うにはどうすれば良いでしょうか。 use Encode; では、"utf8"はありますが、"utf16"というのはありません。 Perlスクリプトに食わせる前に、(テキストエディタなどで手動で文字エンコードさせるのではなく) バッチ処理的に文字列変換できる方法でも構わないのですが、 何か良い方法がありましたら、お教えください。よろしくお願いします。

  • ppmでDBIがインストール出来ません。

    WinXP上のPerlでMySQLをやろうと思ったのですが、ppmからのDBIインストールがうまく行きません。 普通に「ppm install DBI」では出来なくて、プロキシサーバ名とかが良く分からなかったので http://ppm.activestate.com/PPMPackages/zips/6xx-builds-only/ からDBI.zipを直接ダウンロードし、解凍したフォルダ上で ppm install DBI.ppd を実行した所、 Error installing package 'DBI.ppd': Read a PPD for 'DBI.ppd', but it is not intended for this build of Perl (MSWin32-x86-multi-thread) と言うエラーが出てインストール出来ませんでした。 ちなみにPerlは-Vオプションで次のように表示されます。 ------------------------------------------------ This is perl, v5.6.1 built for MSWin32-x86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2001, Larry Wall Binary build 632 provided by ActiveState Corp. http://www.ActiveState.com Built 03:40:44 Jun 3 2002 ------------------------------------------------ ビルドが6xxなのでこのDBI.zipで良いと思うのですが…何かおかしいのでしょうか? あと、私はPerlをC:\PerlでなくC:\usr\localに入れているのですが、これがまずいのでしょうか? どなたか心当たりのある方がいましたら、よろしくお願いします。

  • DBD-ODBCのインストールができません

    助けてください。 DBD-ODBCのインストールがうまくいきません。 インターネットに接続できない環境なのでオフラインで作業をしています。環境は以下の通りです。 ●perl・・・Ver.5.8.8です。 D:\Perl\bin>perl -v This is perl, v5.8.8 built for MSWin32-x86-multi-thread (with 18 registered patches, see perl -V for more detail) Copyright 1987-2007, Larry Wall Binary build 822 [280952] provided by ActiveState http://www.ActiveState.com Built Jul 31 2007 19:34:48 Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit. Complete documentation for Perl, including FAQ lists, should be found on this system using "man perl" or "perldoc perl". If you have access to the Internet, point your browser at http://www.perl.org/, the Perl Home Page. ●DBI・・・Ver.1.58です。 D:\Perl\bin>ppm query dbi レトトトトトトツトトトトトトトトトツトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトツトトトトトトソ ウ name ウ version ウ abstract ウ area ウ テトトトトトトナトトトトトトトトトナトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトナトトトトトトエ ウ DBI ウ 1.58 ウ Database independent interface for Perl ウ perl ウ タトトトトトトチトトトトトトトトトチトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトトチトトトトトトル (1 package installed matching 'dbi') 現象は以下の通りです。 1.DBD-ODBCをactivestate社からダウンロードしました。   DBD-ODBC-1.13.zip 2.回答したファイルを保存しました。   DBD-ODBC.ppdとMSWin32-x86-multi-thread-5.8をd:\perl\bin配下にコピー 3.インストールを実行しました。  D:\Perl\bin>ppm install dbd-odbc.ppd 4.以下のエラーが出てできませんでした。 ppm install failed: Can't find any package that provide DBI version 1.21 for DBD-ODBC どなたか助けてください。 よろしくお願いいたします。

  • Windows漢字フォルダ名を'\'でsplitする方法

    たとえば、 $fullfn = 'C:\Documents and Settings\user\My Documents\記録一覧表.xls'; というようなフルパスファイル名をフォルダ名とファイル名に分割したいのですが、 $dat =~ /^(.*)\\(.*)$/;  #$1は最長マッチングのはず $path = $1; $fn = $2; のような方法で行おうとすると、 上記例のように、文字コードに'\'を含むような漢字(「表」など)がある場合には、上手く分割できません。 path=C:\Documents and Settings\user\My Documents\記録一覧・ fn=.xls のようになってしまいます。 これを上手く行う方法はないでしょうか。よろしくお願いします。 ・Win-2000でActive-Perlを使っています。 This is perl, v5.8.7 built for MSWin32-x86-multi-thread (with 7 registered patches, see perl -V for more detail)

    • ベストアンサー
    • Perl
  • STDIN に関わる動作の違いについて

    幾つかのホストでPerl を使っているのですが STDIN の回りで動作に違いがあり困っています。 test.pl ----- #!/hogehoge/perl print -s STDIN; ----- $ echo 'abcde' | ./test.pl とした場合に、返ってくる結果が違っており 困っております。 この違いは、どこから来るのでしょうか? v5.8.2 built for i386-linux-thread-multi では「0」となりますし v5.8.2 built for i686-linux や version 5.005_03 built for i386-linux では「6」となります v5.8.2 built for i386-linux-thread-multi の時の動作がおかしいようなのですが.... ご教示いただければと思います。

    • ベストアンサー
    • Perl
  • Encode と encoding の同時使用で ISO-2022-JP に encode できない

    CentOS を 5.1 から 5.2 にアップデートした頃から PerlCGI からのメール送信が出来なくなって、調べていたら「ISO-2022-JP への encode がおかいぞ問題」に辿り着きました。 以下のコードで、euc-jp が吐かれてしまいます。 #! /usr/bin/perl -w use encoding('UTF8'); use Encode; binmode(STDOUT); my $text = "<全角文字ですよぉ。>"; print encode('ISO-2022-JP', $text), "\n"; 以下のいずれかで正常に jisコードを吐く様になるのですが、こんなものなんでしょうか? 1 「use encoding('UTF8');」 を 「use utf8;」に替える 2 print の直前に "no encoding;" を入れる CentOS 5.1 では多分正常に ISO-2022-JP への変換ができていたのだと思います。 私の使用するバージョンの Cygwin の Perl でも正常です。 問題のある CentOS5.2 と 問題の無い Cygwin版で、関係しそうなバージョンの違いはありません。 CentOS 5.2: Perl 5.008008 Encode 2.12 Encode::JP 2.01 encoding 2.02 Cygwin: CYGWIN_NT-5.1 **** 1.5.25(0.156/4/2) 2008-04-17 12:11 i686 Cygwin Perl 5.008008 Encode 2.12 Encode::JP 2.01 encoding 2.02 できれば、すでに動いているCGIの use encoding('UTF8'); を直す事なく動く様にしたいのです。

  • Active Perlでsleepを使う。

    OS:Windows XP Home Edition インタプリタ:Active Perl(v5.8.8 built for MSWin32-x86-multi-thread) 簡単なスクリプトを作っていたのですが、 sleepについて質問があります。 #!/usr/bin/perl $a = 3; $b = 4; if($a > $b){ print "aが大きい"; } else{ print "bが大きい"; sleep(20); } このようなプログラムを書いたとき、 「bが大きい」が20秒遅れて表示されるのは 正しいですか? 私は「bが大きい」が表示されてから、20秒待つように 思えるのですが、実際の動きは「bが大きい」が20秒遅れて 表示されます。

    • ベストアンサー
    • Perl
  • perl5.8.6日本語の置換について

    教えてください。perl5.8.6の日本語処理で行き詰まっています。 下記のプログラムをeuc-jpで書いて動作させたところ、s///gの 置換がうまくいきません。 何か間違っているのでしょうか。 weather.pl --------------------------- #! /usr/bin/perl # 使い方: # require "weather.pl"; # $data=weather; use LWP::Simple; use strict; use encoding 'euc-jp'; use Encode qw/from_to/; binmode STDERR,"encoding(euc-jp)"; sub weather{ my $doc; my $adrs = "http://www.jma.go.jp/JMA_HP/jp/warn/text/27.html"; until($doc){ $doc = get "$adrs"; } from_to($doc,'shiftjis','euc-jp'); $doc =~/<tr><td><pre>(.+)<\/pre><\/td><\/tr>/s; $doc = $1; $doc =~s/」/ /g; $doc =~s/パーセント/%/g; $doc =~s/[0-9]/[0-9]/g; $doc; } 1; my $result=weather; print "$result\n"; ---------------------------

    • ベストアンサー
    • Perl
  • じゃらんのAPIでRESTで取得したら文字化け

    はじめて質問です。失礼があったらご容赦ください。 じゃらんAPIのRESTで取得したXMLデータを、単にテキストで 書き出したいのですが、どうしても文字化けしてしまいます。 いろいろ試したのですがどうしても駄目でした。 以下がそのスクリプトです。 どなたかご教示いただければ幸いです。 (作業環境:Windows XP / Perl5.8) use encoding 'utf8'; use Encode; use LWP::Simple; my $key='xxxxxxxxx'; my $url="http://jws.jalan.net/APILite/HotelSearch/V1/?key=$key&pref=120000&l_area=120500&s_area=120508&h_type=1&start=1&count=1"; my $data=get($url) or die; open W,'>:utf8','MyNouhin.txt' or die; print W $data; close W;

専門家に質問してみよう