【问题标题】:Why does JavaScript RegExp lack the "s" flag? [duplicate]为什么 JavaScript RegExp 缺少“s”标志? [复制]
【发布时间】:2018-03-06 15:37:14
【问题描述】:

我喜欢正则表达式。但是,我刚刚遇到在浏览器中运行 JavaScript RegExp 时无法使用 s 标志的问题。我很好奇为什么不包括这个标志?真的很有帮助。

我看到有一个外部库 XRegExp 启用了这个 s 标志(以及其他一些标志),但我也很好奇为什么标准中不存在这些额外(和有用的)标志JavaScript 也是。我也不愿意包含另一个外部库...

这是一个示例,我正在尝试解决检测 WordPress 短代码的打开/关闭标签的问题,其中可能包含换行符(或者我必须在其间插入换行符以改进检测)。

//
// Let's take some input text, e.g. WordPress shortcodes
//
var exampleText = '[buttongroup class="vertical"][button content="Example 1" class="btn-default"][/button][button class="btn-primary"]Example 2[/button][/buttongroup]'

//
// Now let's say I want to extract the shortcodes and its attributes
// keeping in mind shortcodes can or cannot have closing tags too
//
// Shortcodes which have content between the open/closing tags can contain
// newlines. One of the issues with the flags is that I can't use `s` to make
// the dot character.
//
// When I run this on regex101.com they support the `s` flag (probably with the
// XRegExp library) and everything seems to work well. However when running this
// in the browser I get the "Uncaught SyntaxError: Invalid regular expression
// flags" error.
//
var reGetButtons = /\[button(?:\s+([^\]]+))?\](?:(.*)\[\/button\])?/gims
var reGetButtonGroups = /\[buttongroup(?:\s+([^\]]+))?\](?:(.*)\[\/buttongroup\])?/gims

//
// Some utility methods to extract attributes:
//

// Get an attribute's value
//
// @param string input
// @param string attrName
// @returns string
function getAttrValue (input, attrName) {
  var attrValue = new RegExp(attrName + '=\"([^\"]+)\"', 'g').exec(input)
  return (attrValue ?  window.decodeURIComponent(attrValue[1]) : '')
}

// Get all named shortcode attribute values as an object
//
// @param string input
// @param array shortcodeAttrs
// @returns object
function getAttrsFromString (input, shortcodeAttrs) {
  var output = {}
  for (var index = 0; index < shortcodeAttrs.length; index++) {
    output[shortcodeAttrs[index]] = getAttrValue(input, shortcodeAttrs[index])
  }
  return output
}

//
// Extract all the buttons and get all their attributes and values
//
function replaceButtonShortcodes (input) {
  return input
    //
    // Need this to avoid some tomfoolery.
    // By splitting into newlines I can better detect between open/closing tags,
    // however it goes out the window when newlines are within the
    // open/closing tags.
    //
    // It's possible my RegExps above need some adjustments, but I'm unsure how,
    // or maybe I just need to replace newlines with a special character that I
    // can then swap back with newlines...
    //
    .replace(/\]\[/g, ']\n[')
    // Find and replace the [button] shortcodes
    .replace(reGetButtons, function (all, attr, content) {
      console.log('Detected [button] shortcode!')
      console.log('-- Extracted shortcode components', { all: all, attr: attr, content: content })

      // Built the output button's HTML attributes
      var attrs = getAttrsFromString(attr, ['class','content'])
      console.log('-- Extracted attributes', { attrs: attrs })
      
      // Return the button's HTML
      return '<button class="btn ' + (typeof attrs.class !== 'undefined' ? attrs.class : '') + '">' + (content ? content : attrs.content) + '</button>'
    })
}

//
// Extract all the button groups like above
//
function replaceButtonGroupShortcodes (input) {
  return input
    // Same as above...
    .replace(/\]\[/g, ']\n[')
    // Find and replace the [buttongroup] shortcodes
    .replace(reGetButtonGroups, function (all, attr, content) {
      console.log('Detected [buttongroup] shortcode!')
      console.log('-- Extracted shortcode components', { all: all, attr: attr, content: content })
      
      // Built the output button's HTML attributes
      var attrs = getAttrsFromString(attr, ['class'])
      console.log('-- Extracted attributes', { attrs: attrs })
      
      // Return the button group's HTML
      return '<div class="btn-group ' + (typeof attrs.class !== 'undefined' ? attrs.class : '' ) + '">' + (typeof content !== 'undefined' ? content : '') + '</div>'
    })
}

//
// Do all the extraction on our example text and set within the document's HTML
//
var outputText = replaceButtonShortcodes(exampleText)
outputText = replaceButtonGroupShortcodes(outputText)
document.write(outputText)

使用s 标志可以让我轻松地做到这一点,但是由于它不受支持,我无法利用该标志的好处。

【问题讨论】:

  • 警告任何想看regexp101.com的人:不要。它看起来像恶意软件网站。
  • @Andy:而regex101.com(没有p)不是(据我所知)我和其他人已经使用它多年了。马特,这只是问题中代码注释中的错字吗?
  • 哎呀,我的错 - 与所有正则表达式飞来飞去的混乱。我修复了链接????
  • 我已经更新了我的答案来说明这一点,但你在问题中说 “当我在 regex101.com 上运行它时,它们支持 s 标志......”。您只是将其设置为错误的正则表达式“风味”。

标签: javascript regex pcre


【解决方案1】:

它没有什么大逻辑,只是没有被包括在内,就像其他环境中的许多其他正则表达式功能一样,JavaScript 没有(到目前为止)。

它是in the process of being added now。目前第 3 阶段,所以可能是 ES2018,可能不是截至 2017 年 12 月的第 4 阶段,所以将在 ES2018 中,但几率很高,您会看到添加到切割的支持-edge 浏览器今年尽快。

(Look-behind 和 unicode property escapes 也在卡片上...)


旁注:

当我在 regex101.com 上运行它时,它们支持 s 标志...

如果您通过菜单将正则表达式类型设置为 JavaScript,则不会。点击左上角的菜单按钮:

...并将“风格”更改为 JavaScript:

您可能将其保留为默认设置,即 PCRE,它确实支持 s 标志。

他们过去常常使这一点更加明显。因为他们把它藏在菜单上,你不是远程我见过的第一个没有正确设置它的人......

【讨论】:

  • 感谢您的链接!我也设法使用[^] hack 解决了我的问题。
  • @Matt 其实[^] 不是黑客,它匹配非虚无,有效地匹配任何东西。
  • @MattScheurich 您也可以使用[\s\S],它也具有与其他正则表达式引擎一起使用的优势。
猜你喜欢
  • 2023-03-25
  • 2019-04-20
  • 1970-01-01
  • 2015-03-03
  • 2011-03-11
  • 2016-04-14
  • 2020-02-07
  • 2020-05-01
  • 1970-01-01
相关资源
最近更新 更多