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,而不是多行。
Vanuan 2014年

需要注意的是JavaScript的很快就有dotAll修改,所以你可以做/.../s你的点也将匹配新的生产线。截至2017年7月,它已在Chrome浏览器中大显身手。

Answers:


609

您正在寻找/.../s修饰符,也称为dotall修饰符。它强制点.也匹配换行符,默认情况下不这样做

坏消息是它在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标志关联)。
alex 2012年

1
此答案已添加到“ 堆栈修饰符”下的“ 堆栈溢出正则表达式常见问题解答 ”中。
aliteralmind 2014年

40
根据MDN,[^]它还可以匹配JavaScript中的任何字符,包括换行符。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
丹-阿伦

6
对于性能问题,强烈建议使用*?量词而不是*为了避免贪婪。这样可以避免捕获文档的最后一个 <h1>:这可能不是您想要的,并且效率不高,因为regexp会一直寻找<h1>,直到字符串结尾为止,即使之前已经找到它。
KrisWebDev 2014年

9
[^]版本在regexp编译器上更容易,也更简洁。
埃里克·科里

21

您需要s(dotall)修饰符,该修饰符在Javascript中显然不存在-可以.按照@molf的建议用[\ s \ S]替换。的m(多)修饰符品牌^和$匹配行,而不是整个字符串。


4
您可能会添加/ s“修饰符来设置单行模式,而不是多行模式。+1
Cerebrus

九年后,JavaScript现在带有s标志(ES2018)。:-)
TJ Crowder

12

[\s\S]在nodejs 6.11.3中对我不起作用。根据RegExp文档,它说使用[^]适合我的方法。

(点,小数点)匹配除行终止符之外的任何单个字符:\ n,\ r,\ u2028或\ u2029。

在字符集内部,点失去其特殊含义,并且与文字点匹配。

注意,m多行标志不会改变点的行为。因此,要跨多行匹配一个模式,可以使用字符集[^](当然,如果您的意思不是IE的旧版本),它将匹配任何字符,包括换行符。

例如:

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

*在哪里?是0次或多次出现的[^]的非贪婪抓取。


1
对于那些想知道这[^]意味着什么的人:就像一个双重否定:“匹配不在列表中的任何字符”,因此归结为说“匹配任何字符”
特里科特


0

我的建议是,最好用“ \ n”拆分多行字符串,然后将原始字符串的拆分连接起来,成为单行且易于操作。

<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" );
        }
      }
    }

  });
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.