所以说实话,我有一个字符串:
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'"