如何匹配不在两个特殊字符之间的正则表达式?

我有一个像这样的字符串:

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,并提供函数。
  • 在函数中,如果匹配为" ,则递增计数器,并返回"作为替换(基本上没有变化)。 如果匹配是检查计数器是否是偶数:如果甚至提供替换字符串; 否则,只提供匹配的东西。