正規表現で複数行にわたって任意の文字を一致させるにはどうすればよいですか?


356

たとえば、この正規表現

(.*)<FooBar>

一致します:

abcde<FooBar>

しかし、どうすれば複数の行で一致させることができますか?

abcde
fghij<FooBar>

1
明確にするために; 私はもともとEclipseを使用して、複数のファイルを検索して置換していました。以下の回答で私が発見したのは、問題はツールであり、正規表現パターンではないということです。
アンディウク、2008年

2
Eclipseソリューションを探している人は(私がしたように)この質問を見つけて、Eclipse以外のソリューションを受け入れられたものとして見つけるため、フラグ「eclipse」を削除する必要があります。
acme

2
食が言及されたので、今私はこれを検索エンジンで見つけています。ああ恐怖。
ブライアンオルセン

回答:


240

言語によって異なりますが、正規表現パターンに追加できる修飾子が必要です。PHPでは次のようになります。

/(.*)<FooBar>/s

末尾 sにより、ドットは改行を含むすべての文字に一致します


そして、すべての文字ではなく改行だけが必要な場合はどうなりますか?
猶予

3
@Grace:\ nを使用して改行を一致させます
Jeremy

5
少なくともChrome / V8では、sフラグは(今?)無効です。代わりに、代わりに期間マッチャの<FooBarの> /文字クラス(試合空間と非スペース]([\ S \ S] *)/使用詳細は他の回答を参照してください。。
アレン

8
@Allen-JavaScriptはs修飾子をサポートしていません。代わりに、[^]*同じ効果を実行します。
Derek鵺會功夫2015

1
Rubyでは、m修飾子を使用します
Ryan Buckley

358

これを試して:

((.|\n)*)<FooBar>

基本的には、「任意の文字または改行」が0回以上繰り返されます。


5
これは、使用している言語やツールによって異なります。Perl、PHP、CF、C#、sed、awkなど、使用しているものをお知らせください
Ben Doom

39
行末に応じて、必要になる可能性があります((.|\n|\r)*)<FooBar>
Potherca

3
彼はEclipseを使用していると述べました。これは私の意見では正しい解決策です。私は同じ問題を抱えており、これで解決しました。
ダヌビアンセーラー

4
右-質問は日食についてであり、タグも同様です。しかし、受け入れられたソリューションはPHPソリューションです。あなたのソリューションが受け入れられるはずです...
acme

16
これは、複数行の入力を照合するための最悪の正規表現です。ElasticSearchを使用している場合を除き、絶対に使用しないでください。[\s\S]*またはを使用し(?s).*ます。
WiktorStribiżew2016

88

問題は、任意の文字を.パターン一致できるかどうかです。答えはエンジンによって異なります。主な違いは、パターンがPOSIXまたは非POSIX正規表現ライブラリのどちらで使用されるかです。

特記 :正規表現とは見なされません.が、POSIXベースのエンジンと同じように、そこの任意の文字と一致します。

もう一つのメモ そして .デフォルト(で任意の文字に一致するデモ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');tokens含まれているabcde\n fghij項目)。

また、 の正規表現の文法は、デフォルトでドットが改行に一致します。BoostのECMAScript文法では、これをregex_constants::no_mod_msource)でオフにできます。

はどうかと言うと (POSIXベース)、nオプションデモ)を使用:select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

POSIXベースのエンジン

単なる.改行はすでに一致しているため、修飾子を使用する必要はありません。デモ)。

デモ)、デモ)、(TRE、ベースRのデフォルトエンジンなしperl=TRUE、ベースRの場合、perl=TRUEまたはストリンガー / stringiパターンの場合は、(?s)インライン修飾子を使用)(デモ)も.同じ方法で処理します。

ただし、ほとんどのPOSIXベースのツールは、入力を1行ずつ処理します。したがって、.スコープ外であるために改行と一致しません。これをオーバーライドする方法の例をいくつか示します。

  • -複数の回避策がありますが、最も正確ですがあまり安全ではありませんsed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'H;1h;$!d;x;ファイルをメモリに丸呑みします)。行全体を含める必要がある場合は、sed '/start_pattern/,/end_pattern/d' file(最初から削除すると一致する行が含まれて終了します)またはsed '/start_pattern/,/end_pattern/{{//!d;};}' file(一致する行を除外して)を検討できます。
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"-0ファイル全体をメモリに丸呑みし、で-p指定されたスクリプトを適用した後にファイルを印刷します-e)。を使用-000peすると、ファイルが丸呑みされ、「段落モード」がアクティブになります。Perlは、連続する改行(\n\n)をレコード区切りとして使用します。
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file。ここではz、ファイルの丸呑みを(?s)有効にし、.パターンのDOTALLモードを(?i)有効にし、大文字と小文字を区別しないモードを有効に\Kし、これまでに一致したテキストを省略し*?、遅延量指定子であり、(?=<Foobar>)以前の場所と一致します<Foobar>
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" fileMここでファイルの丸呑みを有効にします)。Note pcregrepはMac OS grepユーザーに適したソリューションです。

デモをご覧ください

非POSIXベースのエンジン

  • - 使用する s修飾子PCRE_DOTALL修飾子preg_match('~(.*)<Foobar>~s', $s, $m)デモ
  • - RegexOptions.Singlelineフラグを使用(デモ
    ): var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    - -var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - (?s)インラインオプションを使用:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - s修飾子(または(?s)最初にインラインバージョン)を使用します(デモ):/(.*)<FooBar>/s
  • - re.DOTALL(またはre.S)フラグまたは(?s)インライン修飾子(デモ)を使用します:(m = re.search(r"(.*)<FooBar>", s, flags=re.S)そしてif m:print(m.group(1))
  • - Pattern.DOTALL修飾子(またはインライン(?s)フラグ)を使用します(デモ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - (?s)パターン内修飾子を使用(デモ):regex = /(?s)(.*)<FooBar>/
  • - (?s)修飾子を使用(デモ):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • -使用[^]または回避策[\d\D]/ [\w\W]/ [\s\S]デモ):s.match(/([\s\S]*)<FooBar>/)[1]
  • std::regex)使用[\s\S]またはJS回避策(デモ):regex rex(R"(([\s\S]*)<FooBar>)");
  • -JavaScriptと同じアプローチを使用します([\s\S]*)<Foobar>。(:オブジェクトのMultiLineプロパティは、 RegExp誤って.改行を越えた一致を許可するオプションと見なされることがありますが、実際には、JS正規表現の場合と同様に、文字列ではなく行の開始/終了に一致するように動作^$動作のみが変更されます)動作。)

  • /m -MULTILINE修飾子を使用(デモ):s[/(.*)<Foobar>/m, 1]

  • -基本R PCREの正規表現-使用(?s)regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]デモ
  • -中stringr/ stringiICU正規表現エンジンに電力が供給される正規表現funtions、また、使用(?s)stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]デモ
  • - (?s)最初にインライン修飾子を使用します(デモ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - インライン修飾子を使用するdotMatchesLineSeparatorsか、または(より簡単に)(?s)パターンに渡します。let rx = "(?s)(.*)<Foobar>"
  • -Swiftと同じ(?s)ですが、最も簡単に機能しますがオプションの使用方法は次のとおりです。NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • - (?s)修飾子を使用(デモ):("(?s)(.*)<Foobar>"Googleスプレッドシート=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")

注意事項(?s)

ほとんどの非POSIXエンジンでは、(?s)インライン修飾子(または埋め込みフラグオプション)を使用して強制的.に改行を一致させることができます。

パターンの最初に配置した場合、パターン内(?s)のすべての動作を変更.します。(?s)が先頭の後のどこかに配置されている場合、これがPythonに渡されたパターン.ない限り、その右側にあるものだけが影響を受けreます。Python reでは、(?s)場所に関係なく、パターン全体.が影響を受けます。を使用すると、(?s)効果が停止し(?-s)ます。変更されたグループは、正規表現パターンの指定された範囲にのみ影響を与えるために使用できます(たとえばDelim1(?s:.*?)\nDelim2.*、最初の.*?一致は改行全体で行われ、2番目.*は残りの行のみと一致します)。

POSIXノート

非POSIX正規表現エンジンでは、任意の文字に一致させるために、[\s\S]/ [\d\D]/ [\w\W]構成を使用できます。

[\s\S]正規表現のエスケープシーケンスは角かっこ式内ではサポートされていないため、POSIXでは、(JavaScriptまたは非POSIXエンジンのように)はどの文字とも一致しません。[\s\S]は、単一の文字、\またはsorに一致するブラケット式として解析されSます。


5
プロフィールページなどからこの優れた概要にリンクする必要があります(+1)。
2017年

1
これを後押し項目に追加することをお勧めします。regex_constants名前空間では、flag_type_'s:perl = ECMAScript = JavaScript = JScript = :: boost :: regbase :: normal = 0で、デフォルトはPerlです。プログラマは、#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m正規表現フラグの基本フラグ定義を設定して、それを反映します。そして、アービターは常にインライン修飾子です。どこに(?-sm)(?s).*リセットされます。

1
bashも追加できますか?
パスパティラジャマニカム2018

2
@PasupathiRajamanickam BashはPOSIX正規表現エンジンを使用し、.そこの任意の文字(改行を含む)に一致します。このオンラインBashデモをご覧ください。
WiktorStribiżew2018

1
あなたは揺るがします—これは、私が今まで見た(比較的)複雑な正規表現に関する最も徹底的なミニチュートリアルです。あなたの答えは受け入れられるものになるに値します!功績とGo回答に含めるための追加投票!
グウィネス・ルウェリン

68

Eclipse検索を使用している場合は、「DOTALL」オプションを有効にして「。」を作成できます。行区切り文字を含む任意の文字に一致します。検索文字列の先頭に「(?s)」を追加するだけです。例:

(?s).*<FooBar>

1
どこにもない、インライン修飾子をサポートする正規表現フレーバーのみ、そしてRubyにはありませんwhere (?s)> =(?m)
WiktorStribiżewJul

バッシュのために何か?
パスパティラジャマニカム2018

38

多くの正規表現の方言で、/[\S\s]*<Foobar>/あなたがやりたいことだけをします。ソース


2
そのリンクから:「JavaScriptとVBScriptには、ドットマッチの改行文字を作成するオプションがありません。これらの言語では、[\ s \ S]などの文字クラスを使用して任意の文字を照合できます。」の代わりに。代わりに[\ s \ S](スペースと非スペースに一致)を使用してください。
アレン

32

([\s\S]*)<FooBar>

ドットは、改行(\ r \ n)を除くすべてに一致します。したがって、すべての文字に一致する\ s \ Sを使用します。


これにより、Objective-Cを使用している場合の問題が解決されます[text rangeOfString:regEx options:NSRegularExpressionSearch]。ありがとう!
J.コスタ

1
これは、intelliJのfind&replace正規表現で機能します。
バークレー

これは機能します。しかし、それは最初の発生である必要があります<FooBar>
Ozkan '26 / 09/26


13

私たちも使用できます

(.*?\n)*?

貪欲なしで改行を含むすべてに一致させる

これにより、新しい行がオプションになります

(.*?|\n)*?

8

"."通常、改行は一致しません。ほとんどの正規表現エンジンでは、- Sフラグ(DOTALLandとも呼ばれます)を追加して、改行にも一致SINGLELINEさせることができます"."。それが失敗した場合、のようなことができます[\S\s]


8

Eclipseの場合、次の式が機能しました。

フー

ジャダージャダバー」

正規表現:

Foo[\S\s]{1,10}.*Bar*

5
/(.*)<FooBar>/s

sは、ドット(。)をキャリッジリターンと一致させます。


これは無効のようです(Chrome):text.match(/ a / s)SyntaxError:無効なフラグがRegExpコンストラクター 's'に提供されました
アレン

JavaScript RegExエンジンではサポートされていないためです。sフラグはPCRE(PerlやPHPで利用可能)最も完全なエンジンに存在します。PCREには10個のフラグ(および他の多くの機能)がありますが、JavaScriptには3個のフラグ(gmi)しかありません。
モーガントゥーブレイクイリング

4

Javaベースの正規表現で使用できます [\s\S]


1
それらはバックスラッシュではありませんか?
Paul Draper

正規表現の終わりではなく、正規表現の最後に移動します。例:/ blah / s
RandomInsano

私はあなたがJavaではなくJavaScriptを意味していると思いますか?sJavaでパターンにフラグを追加することができるため、JavaScriptにはsフラグがありません。
3limin4t0r

3

(.|\n)*(たとえば)[\s\S]*(言語の正規表現がそのようなエスケープをサポートしている場合)よりも、を作成する修飾子を指定する方法を見つけるよりも効率が悪い可能性があることに注意してください。改行にも一致します。または、のようなPOSIXyの代替案を使用することもできます[[:space:][:^space:]]*


3

RegexOptions.Singlelineを使用すると、の意味が変わります。改行を含める

Regex.Replace(content、searchText、replaceText、RegexOptions.Singleline);



1

言語内で使用する場合、正規表現は行ではなく文字列に作用します。したがって、入力文字列に複数の行があると仮定すると、正規表現を通常どおり使用できるはずです。

この場合、「<FooBar>」が存在するため、指定された正規表現は文字列全体と一致します。正規表現の実装の詳細に応じて、$ 1の値(「(。*)」から取得)は「fghij」または「abcde \ nfghij」になります。他の人が言ったように、一部の実装では「。」かどうかを制御できます。改行と一致し、選択肢を提供します。

行ベースの正規表現の使用は、通常、egrepなどのコマンドラインで使用されます。


1

私は同じ問題を抱えており、おそらく最善の方法ではなくそれを解決しましたが、うまくいきます。実際の試合を行う前に、すべての改行を置き換えました。

mystring= Regex.Replace(mystring, "\r\n", "")

私はHTMLを操作しているので、この場合、改行は重要ではありません。

私は幸運なしに上記の提案をすべて試しました、私は.Net 3.5 FYIを使用しています


私も.NETを使用(\s|\S)していて、私のためにトリックを行うようです!
Vamshi Krishna

@VamshiKrishna .NETでは、任意の文字(?s).一致させるために使用します。(\s|\S)パフォーマンスが低下するので使用しないでください。
WiktorStribiżew2018

1

JavaScriptでは、[^] *を使用して、改行を含む0〜無限の文字を検索できます。

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>


0

一般的に。改行と一致しないので、試してください((.|\n)*)<foobar>


3
いいえ、それをしないでください。行区切り記号を含む何かと一致させる必要がある場合は、DOTALL(別名/ sまたはSingleLine)修飾子を使用します。(。| \ n)ハックは正規表現の効率を低下させるだけでなく、正しくありません。少なくとも、\ r(キャリッジリターン)および\ n(改行)と一致する必要があります。めったに使用されませんが、他の行区切り文字もあります。しかし、DOTALLフラグを使用する場合、それらについて心配する必要はありません。
アランムーア

1
\ Rは、プラットフォームに依存しないEclipseの改行の一致です。
2009年

@opyateこの小さな宝石は非常に便利なので、これを回答として投稿してください。
jeckhart 2012年

代わりにこれを試すことができます。これは、内側の括弧にマッチし、またオプションで考慮されています\r((?:.|\r?\n)*)<foobar>
SSC-hrep3

0

Javaで特定のifブロックを一致させたい

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

regExpを使用する場合

if \(isTrue(.|\n)*}

メソッドブロックの右中かっこが含まれているので、

if \(!isTrue([^}.]|\n)*}

ワイルドカードの一致から右中かっこを除外します。


0

多くの場合、サブストリングの前の行にまたがるいくつかのキーワードを使用して、サブストリングを変更する必要があります。xml要素を考えてみましょう:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

私たちは81を変更したいとし、他のいくつかの値に、最初に識別40が言う.UID.21..UID.、そして含め、すべての文字をスキップ\nまで.PercentCompleted.。正規表現パターンと置換指定は次のとおりです。

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

サブグループ(.|\n)はおそらく欠落しているグループ$3です。それまでに非キャプチャーにする(?:.|\n)場合は、$3です (<PercentComplete>)。したがって、パターンreplaceSpecは次のようになります。

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

交換は以前と同じように正しく機能します。


0

通常、Powershellで3つの連続する行を検索すると、次のようになります。

$file = get-content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # both

$file -match $pattern

# output
True

奇妙なことに、これはプロンプトではUNIXのテキストになりますが、Windowsではファイル内のテキストになります。

$pattern = 'lineone
linetwo
linethree
'

行末を印刷する方法は次のとおりです。

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# output
lineone\nlinetwo\nlinethree\n

-2

オプション1

1つの方法は、sフラグを使用することです(受け入れられた回答と同じように)。

/(.*)<FooBar>/s

デモ1

オプション2

2番目の方法は、m(複数行)フラグと以下のパターンのいずれかを使用することです。

/([\s\S]*)<FooBar>/m

または

/([\d\D]*)<FooBar>/m

または

/([\w\W]*)<FooBar>/m

デモ2

RegEx回路

jex.imは正規表現を視覚化します。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.