人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PERLの正規化に関しての質問です。

http://yusukebe.com/archives/20090120/133705.html

こちらのページを参考に
色々と試してみているのですが

my @counts = $content =~ /★の合計.*?(\d+)/gm;

の部分がよくわかりません

「★の合計」の文字から(\d+)の間にある.*?を@countsに入れると解釈してたのですが
試してた結果と全く合わず混乱しています。

(\d+)は1個以上の数字にマッチ
.*?は0 回以上の文字(改行を除く)に最短マッチ

と理解しております。

たとえば文字列が
★の合計: 1515 22 234 meでしたら

上記の条件だと
1515が表示されるのですが
(\d+)にも1515が入っていました。($1で表示させました。)

「★の合計」の文字から(\d+)の間にある.*?を@countsの解釈から行くと
「★の合計」の文字から1515の間には何もないはずです。

私がどこか勘違いをしていると思うのですが、どこが間違っているのでしょうか?

上記の正規化の仕組みの解説よろしくお願いします。

●質問者: robopit
●カテゴリ:ウェブ制作 学習・教育
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● たにぐち明生
●50ポイント ベストアンサー

$content = "★の合計: 1515 22 234 me";

だとすると、

/★の合計.*?(\d+)/gm

の .*? にマッチするのは「: 」です。

my @counts = $content =~ /★の合計(.*?)(\d+)/gm;
print $1;

として試してみるとよろしいかと。


robopitさんのコメント
なぜ()をつけるだけでそのように変化するのでしょうか? そもそも、(\d+)に:がはいるのでしたら何も入らないはずなのに 1515が@countsにはいるのでしょうか?

たにぐち明生さんのコメント
おそらくそもそも、 「『★の合計』の文字から(\d+)の間にある.*?を@countsに入れると解釈してたのですが」 というのが誤解で、 @countsに入るのは、\d+です。 「.*?」に「: 」がマッチします。 「\d+」に「1515」がマッチします。 ()でくくった部分はそれぞれ、$1、$2…といった名称の変数に代入されます。 $1、$2…というのはそれぞれ、配列の各要素の変数の名称です。 .*?(\d+)だと、$1=1515 ですが (.*?)(\d+)だと、$1=": ", $2=1515 となります。 最初から言い直せば、 「: 」も文字列なのですから、.*?にマッチします。 $content = "★の合計: 1515 22 234 me"; なのですから、 $content =~ /★の合計.*?(\d+)/gm; とは、 「★の合計」が同じ、 「: 」が「.*?」と、 「1515」が「\d+」と、マッチしています。 my @counts = $content =~ /★の合計.*?(\d+)/gm; は、$1 = 1515 となり、@counts=(1515)となります。 もし、my @counts = $content =~ /★の合計(.*?)(\d+)/gm; に改変すれば、 $1=": ", $2=1515となって、@counts=(": ",1515)となります。 「「★の合計」の文字から1515の間には何もないはずです」も誤解で、 「.*?」にマッチする文字列(「: 」)があったわけです。 「.*?」に何がマッチしているのか分からないから疑問が出てきていたのですから、 この「.*?」に何がマッチしたのかを吐き出させれば解決するわけです。 ですから、 my @counts = $content =~ /★の合計(.*?)(\d+)/gm; print $1; として変えてみれば、「.*?」にマッチしたものの正体が出力されて万事解決するわけですよ。 気になったら、それぞれに何がマッチしているのか、 全部吐き出させてやれば、答えが分かりますよ。

robopitさんのコメント
詳しい解説ありがとうございます 理解できました おかげ様で無事前に進めそうです!

2 ● a-kuma3
●50ポイント

perldoc からの引用です。
http://perldoc.perl.org/perlrequick.html#Extracting-matches

In list context, a match /regex/ with groupings will return the list of matched values ($1,$2,...) . So we could rewrite it as

 ($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/);

括弧でくくった正規表現にマッチした結果を配列で返します。

書いてあることは、同じですが、こんなのも。
http://rfs.jp/sb/perl/02/09.html

リストコンテキストでのパターンマッチ

パターンマッチが、リスト値が要求されるコンテキストで使われると、パターンの中のカッコで括られた部分にマッチしたリストを返します。マッチしたリストは、左から順に$1、$2、$3...と参照できます。マッチが失敗した場合には、空配列が返されます。マッチが成功した場合で、カッコが無い場合には、リスト値が返されます。


robopitさんのコメント
詳しい解説ありがとうございます 理解できました おかげ様で無事前に進めそうです!
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ