为什么 JavaScript RegExp 缺少“s"?旗帜? [英] Why does JavaScript RegExp lack the "s" flag?

查看:48
本文介绍了为什么 JavaScript RegExp 缺少“s"?旗帜?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我看到有一个外部库

...并将风味"更改为 JavaScript:

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

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

I love Regular Expressions. However, I've just now come across the inability to use the s flag when running JavaScript RegExp in the browser. I'm curious as to why is this flag not included? It would be really helpful.

I've seen there's an external library XRegExp which enables this s flag (and a few others), but I'm also curious as to why those extra (and helpful) flags don't exist in standard JavaScript too. I'm also loath to include yet another external library...

Here's an example where I'm trying to solve an issue with detecting open/closing tags for WordPress shortcodes which may have newlines within (or I have to insert newlines between to improve the detection).

//
// 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)

Using the s flag would allow me to do it easily, however since it's unsupported, I can't utilise the benefits of the flag.

解决方案

There was no big logic to it, it just wasn't included, like lots of other regex features other environments have that JavaScript doesn't (so far).

It's in the process of being added now. Currently Stage 3, so maybe ES2018, maybe not Stage 4 as of Dec 2017 so will be in ES2018, but odds are high and you'll see support being added to cutting-edge browsers this year ASAP.

(Look-behind and unicode property escapes are also on the cards...)


Side note:

When I run this on regex101.com they support the s flag...

Not if you set the regex type to JavaScript via the menu. Click the menu button in the top left:

...and change the "flavor" to JavaScript:

You probably left it on its default, which is PCRE, which does indeed support the s flag.

They used to make this more obvious. Since they hid it away on a menu, you're not remotely the first person I've seen not have it set right...

这篇关于为什么 JavaScript RegExp 缺少“s"?旗帜?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆