查找方括号和引号之间的内容



所以说实话,我有一个字符串:

command [stuff] [stuff [inside] this] "string" "another [thing] string"

在我的代码中,我想获取所有带引号的东西,并将它们放在一个数组中,获取最外层括号内的所有东西(外层括号内所有东西(,并将其放在自己的数组中。像这样:

const string = `command [stuff] [stuff [inside] this] "string" "another [thing] string"`;
let quotations = ["string", "another [thing] string"]
let brackets = ["stuff", "stuff [inside] this"] // I do not want to include any brackets found inside of quotation marks

我试着制作一个正则表达式来实现这一点,但我在理解如何设置它时遇到了很多困难。我确实找到了这两个正则表达式,它们在引号和括号中找到了内容,但它们并不是我想要的100%:

// JavaScript Regex
const regexStrings = /(["'])(?:(?=(\?))2.)*?1/g;
const regexBrackets = /[(.*?)]/g;

JavaScript的正则表达式语法不支持递归,因此您需要插入一些代码来处理任意深度的括号嵌套。

因此,我倾向于将字符串拆分为:

  • 引号(以引号开头和结尾,考虑反斜杠转义(
  • 不包含任何'"[]字符的子字符串
  • 单个[]

然后使用深度计数器来跟踪括号的深度,以便您知道何时通过连接标记来构建括号子字符串。

下面是一个片段,使用了比您提供的更复杂的输入字符串:

function solve(str) {
let tokens = str.match(/(['"])((\.|.)*?)1|[^[]'"]+|./g);
let brackets = [];
let quotations = [];
let bracket = "";
let depth = 0;
for (let token of tokens) {
if (token[0] === '"' || token[0] === "'") {
quotations.push(token.slice(1, -1));
} else if (token === "[") {
depth++;
} else if (token === "]") {
depth--;
if (depth < 0) throw "Unbalanced brackets";
if (!depth) {
brackets.push(bracket.slice(1));
bracket = "";
}
}
if (depth) bracket += token;
}
if (depth) throw "Unbalanced brackets";
return {quotations, brackets};
}

const string = String.raw`command [stuff] [stuff [inside [very inside with "escaped " bracket:]" ]] this] "string" "another [thing] string"`;
console.log(solve(string));

下面是一个尝试。

引号的正则表达式将尝试在引号之间查找非引号。

括号的正则表达式将首先尝试匹配引号之间的非引号,然后匹配括号之间的内容
然后筛选出以引号开头的匹配项。

这里没有递归,所以只有1级可选的方括号。

const string = `command [stuff] [stuff [inside] this] "string" "another [thing] string"`;
// JavaScript Regex
const regexStrings = /"[^"]*"|'[^']'/g;
const regexBrackets = /"[^"]*"|'[^']'|([[^[]]*(?:[[^[]]*])?[^[]]*])/g;
let quotations = string.match(regexStrings)
.map(x=>x.replace(/^["']|["']$/g,''));
let brackets = string.match(regexBrackets).filter(x=>!/^["']/.test(x));
console.log(quotations);
console.log(brackets);

为了获得多级嵌套括号,这里有一个额外的标记化器。

function getQuotesAndBrackets(str) {
const re = /(["'])(?:\.|.)*?1|[[]]|[^"'[]]+/g;
let quoted = []; let bracketed = [];
let token = ''; let cnt = 0; let m;
let nest = "";
while(m = re.exec(str)) {
token = m[0][0];
if(cnt==0 && /["']/.test(token)) { quoted.push(m[0]) }
else if(token === '[') { nest += token; cnt += 1 }
else if(token === ']') { nest += token;
if(cnt > 1) { cnt -= 1 }
else { bracketed.push(nest); nest = ""; cnt = 0 }
}
else if(cnt > 0) { nest += m[0] }
}
return {"quotes":quoted, "brackets":bracketed};
} 
// TEST
const string = `all "the [quoted]" [ stuff [inside ["this"] [bracketed] ] ] "thing" [['blah']]`; 
let quotes_and_brackets = getQuotesAndBrackets(string);
console.log(quotes_and_brackets);

假设给定的字符串如下。

'command [stuff] [stuff [inside] this] "string" "another [thing] string"'
bbbbb   bbbbbbbbbbbbbbbbbbb   dddddd   dddddddddddddddddddddd         

我们希望将标记为bbb...(括号内(的值提取到一个数组,并将标记为ddd...(双引号内(的数值提取到第二个数组。这可以通过两个步骤来完成。

步骤1:提取双引号内的所有字符串,并用空字符串替换这些匹配项,包括周围的双引号

将以下正则表达式的匹配项(已设置g标志(替换为空字符串1

"([^"]*)"

这将返回

'command [stuff] [stuff [inside] this]  '
bbbbb   bbbbbbbbbbbbbbbbbbb

我们将在第二步中使用,如下所示。

同样,捕获组1的内容将是'string''another [thing] string',我们必须保存它们。

演示1

这个表达式读作";匹配一个双引号,后跟零个或多个字符,而不是双引号,后面跟一个双引述,字符串以保存到捕获组1的双引号为界;。

步骤2:提取所有用方括号分隔的字符串,这些字符串不在用方括号隔开的字符串内

我们可以通过匹配正则表达式来获得感兴趣的字符串('stuff''stuff [inside] this'(

(?<=[)[^[]]*(?:[[^[]]*])?[^[]]*(?=])

演示2

这个表达式可以分解如下。

(?<=[)     # positive lookbehind asserts match is preceded by '['
[^[]]*    # match 0+ chars other than '[' and ']'
(?:         # begin non-capture group
[        # match '['
[^[]]*  # match 0+ chars other than '[' and ']'
]        # match ']'
)?          # end non-capture group and make it optional
[^[]]*    # match 0+ chars other than '[' and ']'
(?=])      # positive lookahead asserts match is followed by ']'

请注意,此表达式不适用于多个嵌套级别,例如

'[stuff [inside [stuff] like] this]'
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

我给出的正则表达式可以通过扩展我所采用的方法进行修改,以处理任意给定数量的嵌套级别,但对于超过三个级别的嵌套来说,它变得很难处理。

1。或者,我们可以写"(.*?)"。使.*变为惰性(?(可以防止匹配占用字符,包括双引号,直到达到字符串中的最后一个双引号。如果我们使用".*"(贪婪匹配(,我们将获得单个匹配'"string" "another [thing] string'"

最新更新