匹配由特定字符组成的单词,不包括在特殊括号之间

问题描述

我正在尝试匹配仅由该字符类中的字符组成的单词[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>。我也不确定为什么它匹配所有空字符串。

有什么智慧吗? :)

解决方法

模式本质上有两个问题:

  1. 如果您只想匹配字母,则不要在字符类中使用A-z(因为它不仅可以匹配字母 1 )。而是使用a-zA-Z(或A-Za-z)。

  2. 在字符类之后使用*量词将允许空匹配。请改用+量词。

因此,固定模式应为:

[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组

Regex demo

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]);
}