如何匹配不在两个特殊字符之间的正则表达式?
我有一个像这样的字符串:
abcab“ab”ba“a”
如何匹配每个不是由"
? "
分隔的字符串的一部分?我希望匹配这里粗体的所有内容:
a bc a b“ab”b a “a”
我想替换那些匹配(或者更确切地通过用空字符串替换它们来删除它们),因此删除引用的部分以进行匹配将不起作用,因为我希望它们保留在字符串中。 我正在使用Ruby。
假设引号是正确平衡的并且没有转义引号,那么很容易:
result = subject.gsub(/a(?=(?:[^"]*"[^"]*")*[^"]*\Z)/, '')
当且仅当在匹配的a
之前存在偶数引号时,这将用空字符串替换所有s。
说明:
a # Match a (?= # only if it's followed by... (?: # ...the following: [^"]*" # any number of non-quotes, followed by one quote [^"]*" # the same again, ensuring an even number )* # any number of times (0, 2, 4 etc. quotes) [^"]* # followed by only non-quotes until \Z # the end of the string. ) # End of lookahead assertion
如果你可以在引号内转义引号( a "length: 2\""
),它仍然可能但会更复杂:
result = subject.gsub(/a(?=(?:(?:\\.|[^"\\])*"(?:\\.|[^"\\])*")*(?:\\.|[^"\\])*\Z)/, '')
这实质上与上面的正则表达式相同,只用(?:\\.|[^"\\])
代替[^"]
:
(?: # Match either... \\. # an escaped character | # or [^"\\] # any character except backslash or quote ) # End of alternation
js-coder,复活这个古老的问题,因为它有一个没有提到的简单解决方案。 (在为正则表达式赏金任务做一些研究时找到你的问题。)
正如你所看到的,与接受的答案中的正则表达式相比,正则表达式非常小:( ("[^"]*")|a
subject = 'abcab " ab " ba " a "' regex = /("[^"]*")|a/ replaced = subject.gsub(regex) {|m|$1} puts replaced
看到这个现场演示
参考
如何匹配模式除了情况s1,s2,s3
除非……如何匹配模式
适用于正则表达式爱好者的全面正则表达式解决方案,无需考虑性能或代码可读性。
此解决方案假定没有转义语法(使用转义语法, "sbd\"a"
被计为字符串内部)。
伪代码:
processedString = inputString.replaceAll("\\".*?\\"","") // Remove all quoted strings .replaceFirst("\\".*", "") // Consider text after lonely quote as inside quote
然后,您可以在processedString
匹配所需的文本。 如果您将单独引用后的文本视为外部引用,则可以删除第二个替换。
编辑
在Ruby中,上面代码中的正则表达式将是
/\".*?\"/
与gsub
和
/\".*/
与sub
为了解决替换问题,我不确定这是否可行,但值得尝试:
- 宣布一个柜台
- 使用正则表达式
/(\"|a)/
与gsub,并提供函数。 - 在函数中,如果匹配为
"
,则递增计数器,并返回"
作为替换(基本上没有变化)。 如果匹配是检查计数器是否是偶数:如果甚至提供替换字符串; 否则,只提供匹配的东西。