JavaScript正規表現の複数行フラグが機能しない


265

HTMLから文字列を取得する正規表現を作成しましたが、複数行フラグが機能しないようです。

これは私のパターンで、h1タグ内のテキストを取得したいと思います。

var pattern= /<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/mi
m = html.search(pattern);
return m[1];

それをテストするために文字列を作成しました。文字列に「\ n」が含まれる場合、結果は常にnullです。すべての「\ n」を削除すると、/mフラグの有無にかかわらず、正しい結果が得られました。

私の正規表現の何が問題になっていますか?


14
正規表現を使用してHTMLを解析しないでください。HTMLは通常の言語ではありません。HTMLパーサーを使用してください。DOM。それもはるかに簡単です。
Svante、

あなたはマルチラインではなくDOTALLを探しています。
バヌアン2014年

JavaScriptにはすぐdotAll修飾子が含まれるようになるので、それを行うことができ/.../s、ドットも改行と一致します。2017年7月の時点で、Chromeのフラグの後ろにあります。

回答:


609

dotall修飾子/.../sとも呼ばれる修飾子を探しています。また、ドットを強制的に改行に一致させます、デフォルトで一致しません.

悪いニュースは、JavaScriptには存在しないことです (ES2018の時点で存在します以下を参照してください)。良いニュースは、次のように、文字クラス(たとえば\s)とその否定(\S)を一緒に使用することで回避できることです。

[\s\S]

したがって、あなたの場合、正規表現は次のようになります:

/<div class="box-content-5">[\s\S]*<h1>([^<]+?)<\/h1>/i

ES2018の時点で、JavaScriptはs(dotAll)フラグをサポートしているため、最新の環境では、正規表現は記述したとおりにすることができますがs、最後にフラグがありmます(ではなく、m方法^$動作を変更します.)。

/<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/is

5
@simo空白または空白以外の文字に一致し、任意の文字に効果的に一致します。それはようなものだ.が、あまりにもマッチングが空白(\sそれが一致する)手段\n(これは.JavaScriptで行っていない、またはして行うようにすることができるsフラグ)。
アレックス2012年

1
この回答は、「修飾子」の下のスタックオーバーフローの正規表現に関するFAQに追加されました。
aliteralmind 2014

40
MDNによれば[^]、JavaScriptで改行を含むすべての文字に一致するようにも機能します。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…を
Dan Allen

6
パフォーマンスの問題については、貪欲を回避するため*?にで*はなく、数量詞を使用することを強くお勧めします。これは、ドキュメントの最後の <h1>をキャッチするのを回避します。これはおそらく望んでいないことであり、正規表現が以前にすでにそれを見つけたとしても、文字列の終わりまで<h1>を探し続けるので効率的ではありません。
KrisWebDev 2014

9
[^]バージョンは、regexpコンパイラーの方がはるかに簡単で、より簡潔です。
Erik Corry、2015

21

s(dotall)修飾子が必要ですが、これは明らかにJavaScriptには存在しません.。@ molfで提案されているように、[\ s \ S]に置き換えることができます。m(複数行)修飾子ます^と$マッチライン全体ではなく文字列。


4
/ s "修飾子が複数行モードではなく単一行モードを設定することを追加するかもしれません。+ 1
Cerebrus

9年後、JavaScriptにsフラグが付けられました(ES2018)。:-)
TJクラウダー

12

[\s\S]nodejs 6.11.3では動作しませんでした。RegExpのドキュメントに基づいて、[^]私にとってはどれがうまくいくかを使用するように言われています。

(ドット、小数点)は、行終了文字\ n、\ r、\ u2028または\ u2029を除く任意の1文字と一致します。

文字セット内では、ドットは特別な意味を失い、文字どおりのドットと一致します。

mマルチラインフラグはドットの動作を変更しないことに注意してください。したがって、複数行にわたってパターンを照合するには、文字セット[^]を使用できます(もちろん、古いバージョンのIEを意味しない場合)。改行を含むすべての文字に一致します。

例えば:

/This is on line 1[^]*?This is on line 3/m

どこ *?[^]が0回以上出現する貪欲でないグラブです。


1
何を[^]意味するのか疑問に思う方のために:それは二重否定のようなものです:「この空のリストにない任意の文字に一致します」そして「任意の文字に一致する」と言います。
トリンコット2018


0

私の提案では、複数行の文字列を「\ n」で分割し、元の文字列の分割を連結して、1行にして操作しやすくすることをお勧めします。

<textarea class="form-control" name="Body" rows="12" data-rule="required" 
                  title='@("Your feedback ".Label())'
                  placeholder='@("Your Feedback here!".Label())' data-val-required='@("Feedback is required".Label())'
                  pattern="^[0-9a-zA-Z ,;/?.\s_-]{3,600}$" data-val="true" required></textarea>


$( document ).ready( function() {
  var errorMessage = "Please match the requested format.";
  var firstVisit = false;

  $( this ).find( "textarea" ).on( "input change propertychange", function() {

    var pattern = $(this).attr( "pattern" );
    var element = $( this );

    if(typeof pattern !== typeof undefined && pattern !== false)
    {
      var ptr = pattern.replace(/^\^|\$$/g, '');
      var patternRegex = new RegExp('^' + pattern.replace(/^\^|\$$/g, '') + '$', 'gm');     

      var ks = "";
      $.each($( this ).val().split("\n"), function( index, value ){
        console.log(index + "-" + value);
        ks += " " + value;
      });      
      //console.log(ks);

      hasError = !ks.match( patternRegex );
      //debugger;

      if ( typeof this.setCustomValidity === "function") 
      {
        this.setCustomValidity( hasError ? errorMessage : "" );
      } 
      else 
      {
        $( this ).toggleClass( "invalid", !!hasError );
        $( this ).toggleClass( "valid", !hasError );

        if ( hasError ) 
        {
          $( this ).attr( "title", errorMessage );
        } 
        else
        {
          $( this ).removeAttr( "title" );
        }
      }
    }

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