2016-05-24 8 views
1

Perlでマルチライン正規表現を行う方法については、多くの質問があります。ほとんどの人は、ドットマッチを改行にするスイッチsについて言及しています。しかし、私は正確なフレーズ(パターンではない)と一致させたいので、改行がどこになるのか分かりません。ですから問題は:.と一致するのではなく、改行を無視できますか?ドットのないPerl正規表現マルチラインマッチ

MWE:

$pattern = "Match this exact phrase across newlines"; 

$text1 = "Match\nthis exact\nphrase across newlines"; 
$text2 = "Match this\nexact phra\nse across\nnewlines"; 

$text3 = "Keep any newlines\nMatch this exact\nphrase across newlines\noutside\nof the match"; 

$text1 =~ s/$pattern/replacement text/s; 
$text2 =~ s/$pattern/replacement text/s; 
$text3 =~ s/$pattern/replacement text/s; 

print "$text1\n---\n$text2\n---\n$text3\n"; 

私は、パターンスペースの代わりに("Match.this.exact.phrase")にドットを置くことができますが、それは第二の例では動作しません。前処理としてすべての改行を削除できますが、3番目の例のように、一致の一部ではない改行を保持したいと思います。

所望の出力:

replacement text 
--- 
replacement text 
--- 
Keep any newlines 
replacement text 
outside 
of the match 
+0

ほとんどの場合、改行をスペースとして扱います。それでは、あなたがそれを無視したいという時があります。いずれかをするのは簡単です。両方をすることは不可能です。 – ikegami

答えて

2

「正確な」パターンを変更して、どこにでも改行を一致させ、空白ではなく改行を許可するように思えます。そのためにパターンを変更してください:

$pattern = "Match this exact phrase across newlines"; 
$pattern =~ s/\S\K\B/\n?/g; 
$pattern =~ s/ /[ \n]/g; 
+0

注:これは '$ pattern'が正規表現パターンではなく、文字列リテラルを正確に見つけることを前提としています。 – ikegami

+0

これは '$ pattern =" * "'と '$ text =" * "'と一致しません。 – ikegami

+0

これは '$ pattern =" foo-bar "と' $ text = "foo \ n-bar" 'と一致しません。 – ikegami

3

ただ、空白や改行にマッチする文字クラスリテラルのスペースに置き換えます。

$pattern = "Match[ \n]this[ \n]exact[ \n]phrase[ \n]across[ \n]newlines"; 

それとも、あなたはもっと寛大になりたい場合は、\sを使用します\sも改行に一致しているため、\s+となります。

+0

私の2番目の例( 'phra \ nse')はどうですか? – Marijn

1

それは確かに醜いですが、それは動作します:単語内の文字のすべてのペアのために

M\n?a\n?t\n?c\n?h\st\n?h\n?i\n?s\se\n?x\n?a\n?ct\sp\n?h\n?r\n?a\n?s\n?e\sa\n?c\n?r\n?o\n?s\n?s\sn\n?e\n?w\n?l\n?i\n?n\n?e\n?s 

\n?とそれらの間に改行を許可します。正規表現内の各スペースを\sに置き換えます。 )

Check it out at regex101;

は使用できないかもしれないが、それは仕事が行われます。

3

ほとんどの場合、改行をスペースとして扱います。それがすべての場合、必要なのは

$text =~ s/\n/ /g; 
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/ 

です。それでは無視してください。それはあなたがやってみたかったのすべてのなら、あなたが必要があると思い、すべては

$text =~ s/\n//g; 
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/ 

の両方をやっているあなたはマッチする正規表現パターンを持っている場合は不可能に近いです。しかし、あなたは文字通りのテキストにマッチしたいと思われるので、いくつかの可能性が開かれます。

(my $pattern = $text_to_find) 
    =~ s/(.)/ $1 eq " " ? "[ \\n]" : "\\n?" . quotemeta($1) /seg; 
$pattern =~ s/^\\n\?//; 
$text =~ /$pattern/ 
+0

がテストされた池上の答えを使用してください。いくつかの修正を加えました。 – ikegami

+0

私は希望のマッチの直前に改行を取り除くと思います – ysth