JavaScript 正则表达式多行标志不起作用

IT技术 javascript regex
2021-01-31 11:06:23

我写了一个正则表达式来从 HTML 中获取字符串,但似乎多行标志不起作用。

这是我的模式,我想在h1标签中获取文本

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

我创建了一个字符串来测试它。当字符串包含“\n”时,结果始终为空。如果我删除了所有的“\n”,无论有没有/m标志,它都会给我正确的结果

我的正则表达式有什么问题?

5个回答

您正在寻找/.../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
[^] 仅适用于 JavaScript(和其他 ECMAScript 实现),如果您尝试在其他风格中使用它,可能会产生意想不到的结果。
2021-03-16 11:06:23
对于性能问题,强烈建议使用*?量词而不是*为了避免贪婪。这将避免捕获文档最后一个<h1>:这可能不是您想要的并且效率不高,因为 regexp 将继续查找 <h1> 直到字符串的末尾,即使它之前已经找到它。
2021-03-18 11:06:23
@simo 匹配任何空白或非空白字符,有效匹配任何字符。就像.,但也匹配空格 ( \s) 意味着它匹配\n(这.在 JavaScript 中不匹配,或者可以与s标志有关)。
2021-03-26 11:06:23
[^] 版本在 regexp 编译器上更容易,也更简洁。
2021-04-03 11:06:23
根据 MDN,[^]它还可以匹配 JavaScript 中的任何字符,包括换行符。参见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-08 11:06:23

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

您可能会添加 /s" 修饰符设置单行模式而不是多行模式。+1
2021-03-24 11:06:23
九年后,JavaScript 现在有了这个s标志(ES2018)。:-)
2021-04-10 11:06:23

[\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 次或多次出现 [^] 的非贪婪抓取。

对于那些想知道什么[^]意思的人:这就像双重否定:“匹配不在列表中的任何字符,因此归结为“匹配任何字符”
2021-04-08 11:06:23

dotall 修饰符实际上已经在 2018 年 6 月变成了 JavaScript,也就是 ECMAScript 2018。https
://github.com/tc39/proposal-regexp-dotall-flag

const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`.
re.test('foo\nbar');
// → true
re.dotAll
// → true
re.flags
// → 's'

我的建议是,最好用“\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" );
        }
      }
    }

  });
});