问题描述
我正在尝试匹配仅由该字符类中的字符组成的单词:[A-z'\\/%]
,不包括情况,
- 它们在
<
和>
之间 - 它们在
[
和]
之间 - 它们在
{
和}
之间
所以,说我有这个有趣的字符串:
[beginning]<start>How's {the} /weather (\\today%?)[end]
我需要匹配以下字符串:
[ "How's","/weather","\\today%" ]
我已经尝试过使用以下模式:
/[A-z'/\\%]*(?![^{]*})(?![^\[]*\])(?![^<]*>)/gm
但是由于某些原因,它匹配:
[ "[beginning]","","How's","\\today%","[end]","" ]
我不确定为什么我的模式允许[
和]
之间的内容,因为我使用了(?![^\[]*\])
,并且类似的方法似乎对无效匹配{these cases}
和<these cases>
。我也不确定为什么它匹配所有空字符串。
有什么智慧吗? :)
解决方法
模式本质上有两个问题:
-
如果您只想匹配字母,则不要在字符类中使用
A-z
(因为它不仅可以匹配字母 1 )。而是使用a-zA-Z
(或A-Za-z
)。 -
在字符类之后使用
*
量词将允许空匹配。请改用+
量词。
因此,固定模式应为:
[A-Za-z'/\\%]+(?![^{]*})(?![^\[]*\])(?![^<]*>)
Demo 。
1 [A-z]
字符类表示”匹配具有65到122之间的ASCII码的任何字符” 。问题在于91和95之间的代码不是 字母(这就是为什么原始模式匹配'['和']'等字符的原因。
用正则表达式将其分割:
let data = "[beginning]<start>How's {the} /weather (\\today%?)[end]";
let matches = data.split(/\s*(?:<[^>]+>|\[[^\]]+\]|\{[^\}]+\}|[()])\s*/);
console.log(matches.filter(v => "" !== v));
,
您可以使用alternation匹配所有不需要的情况,并将角色类放在捕获组中以捕获要保留的内容。
[^
是negated character class,它与除指定字符外的任何字符匹配。
(?:\[[^\][]*]|<[^<>]*>|{[^{}]*})|([A-Za-z'/\\%]+)
说明
-
(?:
非捕获组-
\[[^\][]*]
从开启到结束[]
-
|
或 -
<[^<>]*>
从开启到结束<>
-
|
或 -
{[^{}]*}
从开启到结束{}
-
-
)
关闭非捕获组 -
|
或 -
([A-Za-z'/\\%]+)
重复角色类别1次以上,以防止空匹配并捕获到第1组
const regex = /(?:\[[^\][]*]|<[^<>]*>|{[^{}]*})|([A-Za-z'/\\%]+)/g;
const str = `[beginning]<start>How's {the} /weather (\\\\today%?)[end]`;
let m;
while ((m = regex.exec(str)) !== null) {
if (m[1] !== undefined) console.log(m[1]);
}