我希望匹配所有内容,但没有引用的字符串。
我可以将所有引用的字符串与此匹配:/(("([^"\\]|\\.)*")|('([^'\\]|\\.)*'))/
所以我尝试匹配所有内容但没有带引号的字符串:/[^(("([^"\\]|\\.)*")|('([^'\\]|\\.)*'))]/
但它不起作用。
我想只使用正则表达式,因为我想要替换它并希望在它之后获取引用的文本。
string.replace(regex, function(a, b, c) {
// return after a lot of operations
});
引用字符串对我来说就是这样“坏字符串”或者'酷字符串'
所以,如果我输入:
he\'re is "watever o\"k" efre 'dder\'4rdr'?
它应输出以下匹配项:
["he\'re is ", " efre ", "?"]
而且我不想替换它们。
我知道我的问题非常困难但并非不可能!没有什么是不可能的。
由于
答案 0 :(得分:9)
这可以做到,但有点复杂。
result = subject.match(/(?:(?=(?:(?:\\.|"(?:\\.|[^"\\])*"|[^\\'"])*'(?:\\.|"(?:\\.|[^"'\\])*"|[^\\'])*')*(?:\\.|"(?:\\.|[^"\\])*"|[^\\'])*$)(?=(?:(?:\\.|'(?:\\.|[^'\\])*'|[^\\'"])*"(?:\\.|'(?:\\.|[^'"\\])*'|[^\\"])*")*(?:\\.|'(?:\\.|[^'\\])*'|[^\\"])*$)(?:\\.|[^\\'"]))+/g);
将返回
, he said.
, she replied.
, he reminded her.
,
来自此字符串(为了清楚起见,添加了换行符并删除了引号):
"Hello", he said. "What's up, \"doc\"?", she replied.
'I need a 12" crash cymbal', he reminded her.
"2\" by 4 inches", 'Back\"\'slashes \\ are OK!'
说明:(有点令人难以置信)
打破正则表达式:
(?:
(?= # Assert even number of (relevant) single quotes, looking ahead:
(?:
(?:\\.|"(?:\\.|[^"\\])*"|[^\\'"])*
'
(?:\\.|"(?:\\.|[^"'\\])*"|[^\\'])*
'
)*
(?:\\.|"(?:\\.|[^"\\])*"|[^\\'])*
$
)
(?= # Assert even number of (relevant) double quotes, looking ahead:
(?:
(?:\\.|'(?:\\.|[^'\\])*'|[^\\'"])*
"
(?:\\.|'(?:\\.|[^'"\\])*'|[^\\"])*
"
)*
(?:\\.|'(?:\\.|[^'\\])*'|[^\\"])*
$
)
(?:\\.|[^\\'"]) # Match text between quoted sections
)+
首先,您可以看到有两个相似的部分。这两个前瞻断言都确保前面的字符串中有偶数个单/双引号,而忽略了相反类型的转义引号和引号。我将用单引号部分显示它:
(?= # Assert that the following can be matched:
(?: # Match this group:
(?: # Match either:
\\. # an escaped character
| # or
"(?:\\.|[^"\\])*" # a double-quoted string
| # or
[^\\'"] # any character except backslashes or quotes
)* # any number of times.
' # Then match a single quote
(?:\\.|"(?:\\.|[^"'\\])*"|[^\\'])*' # Repeat once to ensure even number,
# (but don't allow single quotes within nested double-quoted strings)
)* # Repeat any number of times including zero
(?:\\.|"(?:\\.|[^"\\])*"|[^\\'])* # Then match the same until...
$ # ... end of string.
) # End of lookahead assertion.
双引号部分的作用相同。
然后,在字符串中这两个断言成功的每个位置,正则表达式的下一部分实际上试图匹配某些东西:
(?: # Match either
\\. # an escaped character
| # or
[^\\'"] # any character except backslash, single or double quote
) # End of non-capturing group
整个事情重复一次或多次,尽可能多次。 /g
修饰符确保我们在字符串中获得所有匹配项。
答案 1 :(得分:1)
这是一个经过测试的功能,可以解决这个问题:
function getArrayOfNonQuotedSubstrings(text) {
/* Regex with three global alternatives to section the string:
('[^'\\]*(?:\\[\S\s][^'\\]*)*') # $1: Single quoted string.
| ("[^"\\]*(?:\\[\S\s][^"\\]*)*") # $2: Double quoted string.
| ([^'"\\]*(?:\\[\S\s][^'"\\]*)*) # $3: Un-quoted string.
*/
var re = /('[^'\\]*(?:\\[\S\s][^'\\]*)*')|("[^"\\]*(?:\\[\S\s][^"\\]*)*")|([^'"\\]*(?:\\[\S\s][^'"\\]*)*)/g;
var a = []; // Empty array to receive the goods;
text = text.replace(re, // "Walk" the text chunk-by-chunk.
function(m0, m1, m2, m3) {
if (m3) a.push(m3); // Push non-quoted stuff into array.
return m0; // Return this chunk unchanged.
});
return a;
}
此解决方案使用带有替换回调函数的String.replace()
方法逐段“遍历”字符串。正则表达式有三个全局替代品,每个部分一个; $ 1:单引号,$ 2:双引号,$ 3:非引用子串,每个非引用的块被推送到返回数组。它正确处理所有转义字符,包括转义引号,内部和外部引用字符串。单引号子串可以包含任意数量的双引号,反之亦然。非法孤立引号被删除,用于将未引用的部分划分为两个块。请注意,此解决方案不需要环视,只需要一次通过。它还实现了Friedl的“Unrolling-the-Loop”效率技术并且非常有效。
附加:以下是使用原始测试字符串测试函数的一些代码:
// The original test string (with necessary escapes):
var s = "he\\'re is \"watever o\\\"k\" efre 'dder\\'4rdr'?";
alert(s); // Show the test string without the extra backslashes.
console.log(getArrayOfNonQuotedSubstrings(s).toString());
答案 2 :(得分:-5)
你无法反转正则表达式。你所尝试的是从中创建一个角色类并反转它 - 但是为了做到这一点你必须逃避所有右括号“\]”。
编辑:我本来是
/(^|" |' ).+?($| "| ')/
这匹配引用字符串的开头或结尾之间的任何内容(非常简单:引号加空格)和字符串的结尾或引用字符串的开头(空白加引号)。当然,这不会处理任何不遵循方案/ ['"].*['"] /
的转义序列或引用。有关更详细的表达,请参阅上面的答案: - )