こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

perl でこのマッチは失敗しますか?

perl でこのマッチは失敗しますか?

my $one = "FEFRGrgarGEEeg+05fweaEFJIEI+A";
my $str = "FEFRGrgarGEEeg+05fweaEFJIEI+A";
if($str =~ m/$one/){
print "same";
}else{
print "difference";
}
exit;

5時間ほど悩んでそれらしいところを見つけたのですが、この部分で失敗しているようでした。
「+」記号がある為だと思うのですが、何故、このようなことになるのでしょうか?
このように、失敗するような避けるべき文字ありますか?

また、+記号などがあっても正しくマッチを使う方法はありますでしょうか?

投稿日時 - 2010-09-24 15:52:14

QNo.6204889

暇なときに回答ください

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

少なくとも最近の Perl なら「文字列に埋め込まれた \E によって \Q の効果が終了する」ということはないです. たとえば
use feature 'say';
$x = "a+\\Eb*?";
say qr/\Q$x\E/;
を実行すると
(?-xism:a\+\\Eb\*\?)
となり, \Q の効果が $x に埋め込まれた \E を越えて現れていることが確認できます. また, 実際に $x =~ /\Q$x\E/ でマッチさせても正しくマッチできています.

投稿日時 - 2010-09-28 17:18:21

お礼

\Q \E の信頼性に不安があり使っていなかったですが、最近のPerlであれば安心して使えるのですね。
実例も紹介して頂き誠にありがとうございました!

投稿日時 - 2010-10-02 17:53:55

ANo.5

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

失礼しました。
よく確かめたところ、確かに m/\Q$x\E/ という使いかたで、$xの中に正規表現のメタ文字があっても効果を発しないの確認しました。
直接記述した場合は、\Eがあるとそこで\Qによる無効化が切れるようです。

申し訳ありません。

投稿日時 - 2010-09-29 18:53:47

補足

回答いただきありがとうございます。
とても参考になりました。

投稿日時 - 2010-10-02 17:52:29

ANo.4

・バージョン違い
どの言語にもある問題です。Perlに限ったことではありません。
例えば、 C#3.0で追加されたラムダ式はC#2.0では使えません。

・index
index自体は特殊な変換を一切行いません。
が、引数に使う文字列を指定する段階で変換される場合はあります。 例えば
my $a = "bbb";
index( $str, "x$a" )
とあった場合、""の中の$aが展開され,'xbbb'になります。
これは、ダブルクォートによる展開であって,indexによる変換ではありません。

・\Q\E
たとえば、$oneの中に\Eという文字列が含まれていた場合、
\Q$one\E
は$oneの中の\Eの直前まではそのまま、$oneの中の\E以降は正規表現としての特殊な意味を持つものとして解釈されます。

・UTF-8
これはまた別の問題です。
"perl unicode" で検索してください。

投稿日時 - 2010-09-28 09:47:51

ANo.3

> 何故、このようなことになるのでしょうか?

m/$one/
は、変数$oneが展開されたあとで、それを「正規表現」として解釈します。
「変数$oneに入っている文字列にマッチ」ではありません。
$oneの中に正規表現での特殊な意味を持つ文字列が含まれていたら、その特殊な意味の通りに解釈されます。
特殊な表現はPerlのバージョンによっても若干違います。
特にPerlの正規表現は多機能で、特殊な表現もたくさんあります。
詳しくは、 「perl 正規表現」で検索するとか、 man perlreを読むとかしてください。


対策は既に出ている
・検索文字列を正規表現として適したものにする:特殊文字を\で無効にする、等
・\Q\Eで括って、特殊な意味を無効にする
があります。


また、単に二つの文字列が等しいかどうかを判定するなら
$str eq $one
と eq 演算子が使えます。(==ではありません)

文字列を含むかどうかを調べるだけなら
index $str, $one
rindex $str, $one
とindex関数,rindex関数が使えます。

投稿日時 - 2010-09-24 19:23:04

お礼

詳細な説明ありがとうございます!

特殊な意味を持つ文字はいろいろあり、バージョンによっても違うのですね。
プログラムはperlとVC#が少しし使えませんが、時々、perlは嫌いという人を聞くのですが、
他の言語ではこういったことが少ないのでしょうか?

なお、今回は、一部マッチが必要ですので、indexも良いのですが、こちらは、特殊な意味を持つ文字も評価せず判断されるのでしょうか?

\Q\Eについて以前は全てのマッチで使っていたのですが、かなり昔で、どこで読んだか忘れてしまいましたが、万能ではなく誤作動する可能性があるので、使わない方がよいと聞いたことがあります。今は問題ないのでしょうか?(UTF8なら問題ない?)

もし、こちらの疑問についてもご存じでしたら回答いただけると幸いです。

投稿日時 - 2010-09-28 00:10:04

ANo.2

文字列 $str の内容にマッチさせたいなら
/\Q$str\E/
が最も簡単.

投稿日時 - 2010-09-24 16:48:03

お礼

とりあえず、書き換えてみたところ、正常に動作するようになりました。
回答いただきありがとうございます。

投稿日時 - 2010-09-28 00:01:41

ANo.1

 + は、その直前の文字が1回以上続く正規表現のメタ文字(記号)なので、+ 自体をヒットさせたりするのでしたら、直前に \ (スラッシュバック)を付ければ良いと思います。 → \+。

 メタ文字の他には、 . * ? ^ $ などがあります。

投稿日時 - 2010-09-24 16:15:07

お礼

回答いただきありがとうございます。
正規表現のメタ文字解釈になるのですか。
ありがとうございます。とても、参考になりました。

投稿日時 - 2010-09-28 00:01:05

あなたにオススメの質問