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の間には何もないはずです。

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

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

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2012/02/18 02:46:47
  • 終了:2012/02/18 14:27:51

ベストアンサー

id:hits No.1

たにぐち明生回答回数39ベストアンサー獲得回数62012/02/18 04:02:50

ポイント50pt

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

だとすると、

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

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

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

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

他1件のコメントを見る
id:hits

おそらくそもそも、
「『★の合計』の文字から(\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;
として変えてみれば、「.*?」にマッチしたものの正体が出力されて万事解決するわけですよ。

気になったら、それぞれに何がマッチしているのか、
全部吐き出させてやれば、答えが分かりますよ。

2012/02/18 14:16:44
id:robopit

詳しい解説ありがとうございます
理解できました
おかげ様で無事前に進めそうです!

2012/02/18 14:27:33

その他の回答(1件)

id:hits No.1

たにぐち明生回答回数39ベストアンサー獲得回数62012/02/18 04:02:50ここでベストアンサー

ポイント50pt

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

だとすると、

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

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

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

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

他1件のコメントを見る
id:hits

おそらくそもそも、
「『★の合計』の文字から(\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;
として変えてみれば、「.*?」にマッチしたものの正体が出力されて万事解決するわけですよ。

気になったら、それぞれに何がマッチしているのか、
全部吐き出させてやれば、答えが分かりますよ。

2012/02/18 14:16:44
id:robopit

詳しい解説ありがとうございます
理解できました
おかげ様で無事前に進めそうです!

2012/02/18 14:27:33
id:a-kuma3 No.2

a-kuma3回答回数4442ベストアンサー獲得回数18252012/02/18 13:41:23

ポイント50pt

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...と参照できます。マッチが失敗した場合には、空配列が返されます。マッチが成功した場合で、カッコが無い場合には、リスト値が返されます。

id:robopit

詳しい解説ありがとうございます
理解できました
おかげ様で無事前に進めそうです!

2012/02/18 14:27:30

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません