首页 > 解决方案 > 如果在字符串 A 之前的任何位置找到字符串 B,则尝试匹配字符串 A

问题描述

我想要做的是,如果一个字符串由一些以“!”开头的子字符串组成 封装在 "[" 和 "]" 中,通过空格将这些括号与字符串的其余部分分开,例如 "[!foo]" --> "[ !foo ]", "[!bar]" --> "[ !bar ]" 等。由于该子字符串可以是可变长度的,我认为这必须使用正则表达式来完成。我的想法是分两步来做——首先分开第一个括号,然后分开第二个括号。

第一个并不难;正则表达式是公正的\[!,所以我可以str = str.replace(/\[!/g, "[ !");用 Javascript 来做。这是我无法上班的第二部分。

因为现在,如果字符串文字“[!”,我需要匹配“]” 在它之前的任何地方都可以找到。所以一个简单的正向向后看是不匹配的,因为它只直接看后面:(?<=\Q[ !\E)\]不匹配。

而且我仍然不明白为什么,但是我不允许正面向后看非固定长度;在控制台中(?<=\Q[ !\E.*)\]抛出错误,并且此正则表达式调试器产生一个模式错误,解释“后视中的量词使其宽度不固定”。Syntax Error: Invalid regular expression: missing /

在后视和捕获组之间放置一个非固定宽度的非捕获组不起作用;(?<=\Q[ !\E)(?:.*)\]不匹配。

一件行不通的事情就是试图匹配“[!” 在字符串的开头,因为整个 "[!foo]" 字符串实际上本身就是一个更大字符串的子字符串,并且不在开头。

我错过了什么?

标签: regexregex-lookaroundslookbehind

解决方案


使用 2 个正向环视,您可以断言左侧是一个左方括号(?<=\[)

然后匹配任何字符,除了]使用前面带有感叹号的否定字符类 ![^[\]]+,并断言右边是一个右方括号,使用(?=])

请注意,在 Javascript 中,lookbehind 尚未得到广泛支持。

(?<=\[)![^[\]]+(?=])

替换中使用匹配的子字符串$&

正则表达式演示

[
  "[!foo]",
  "[!bar]"
].forEach(s =>
  console.log(s.replace(/(?<=\[)![^[\]]+(?=])/g, " $& "))
)


或者您也可以使用 3 个捕获组:

(\[)(![^\]]+)(\])

在更换使用

$1 $2 $3

正则表达式演示

[
  "[!foo]",
  "[!bar]"
].forEach(s =>
  console.log(s.replace(/(\[)(![^\]]+)(\])/g, "$1 $2 $3"))
)


推荐阅读