我正在寻找使用.NET正则表达式查找不在双引号内的每个单词。下面是一些示例文本:
Hello world I want to get all of these words as a match "but not these ones...
because they're inside a string. And maybe I'll \"escape\" the quotes too." Also,
these words should match. Now we're outside of the string. And I can't escape
quotes; \"this still shouldn't be matched."所以我想要匹配:
Hello, world, I, want, to, get, all, of, these, words, as, a, match, Also,
these, words, should, match, Now, we, re, outside, of, the, string, And, I,
can, t, escape, quotes是否可以使用.NET正则表达式外部堆栈和断言?我已经走了这么远了:
(?<=(?(rstack)|(?!))(?<-rstack>").*?(?<rstack>").*?)\w+... same thing for fstack当然,它不起作用。
发布于 2012-01-24 21:53:44
此表达式使用平衡组返回所需的单词。匹配表达式后,引号中的单词可以作为m.Groups["word"].Captures.OfType<Capture>.Select(c=>c.Value)进行访问。通过在模式中包含可选断言,如果引号不平衡,则匹配可能会失败;如果从表达式中删除,则忽略无关的引号。
以下是包含图案并打印所需输出的驱动程序。
string input = @"Hello world I want to get all of these words as a match ""but not these ones... because they're inside a string. And maybe I'll \""escape\"" the quotes too."" Also, these words should match. Now we're outside of the string. And I can't escape quotes; \""this still shouldn't be matched.""";
string pattern = @"(?>
^(?:
#capture word only if not inside a quotation
(?(quote)\w+|(?<word>\w+))
(?:
([^\w""]*|$)
(?(quote)
#if within a quote, close unless escaped
(?:(?<=\\)\""|(?<-quote>(?<!\\)\""))
|
#if not within a quote, open quote
(?<quote>\"")
)?
)*
)*
)$
(?(quote)(?!)) # will fail to match if extra quotes
# if line removed, will ignore extra quote";
RegexOptions options = RegexOptions.IgnorePatternWhitespace;
Match m = Regex.Match(input, pattern, options);
if (!m.Success) Console.WriteLine("Failed");
else
foreach (
var word in m.Groups["word"]
.Captures
.OfType<Capture>()
.Select(a => a.Value))
Console.WriteLine(word);发布于 2012-01-23 12:05:05
我认为,与其匹配引号外的单词,不如匹配引号内的单词,并将其替换为'‘。
在这种情况下,我建议你看看this question和@RicardoNolde的答案:
(?>(?(STR)(?(ESC).(?<-ESC>)|\\(?<ESC>))|(?!))|(?(STR)"(?<-STR>)|"(?<STR>))|(?(STR).|(?!)))+(请参阅他的问题以获得比我更好的解释,因为我不熟悉.NET引擎)。
这将匹配引号内的所有单词。如果你删除它们(即用‘’替换),然后用@"\b(\w+)\b"匹配结果字符串,你就对了。
然而,你会有问题,除非在你的字符串中:
\"和相应的" )"This is a quote that contains another "quote", tricky!"可以说在引号内包含D14和D15)。H216F217(前面的正则表达式似乎适用于\"this still shouldn't be matched"的示例,但如果将其更改为"this still shouldn't be matched\" but this should. "hi",则会出现问题,因为内部\"被视为转义引号,而不是平衡对的一部分)。
也就是说,如果您的文本满足我上面提到的这三个规则,那么您可以使用普通的正则表达式做您想做的事情(尽管我觉得既然您使用的是.NET,那么您也可以利用它的堆栈特性):
(?<!")\b[a-zA-Z]+\b(?=(?>((\\"|[^"])*)"(?>(\\"|[^"])*)")*(\\"|[^"])*$)这意味着“匹配任何后跟偶数个非转义引号的单词”。逻辑是,由于引号是成对的,如果您不在一组引号内,则剩下偶数个(未转义的)引号。
here ( (?>...)是为了避免正则表达式引擎进行不必要的回溯,这样性能会更好)。(注意:我将不匹配的引号\"this still shouldn't be matched"更改为"this still shouldn't be matched",以便输入符合上述三条规则)。
还要注意,你不能说“匹配任何后面跟着偶数个引号的单词”(包括转义的引号),因为这样你就会在匹配嵌套引号内的单词时遇到问题。例如,Hello world "this is a quote \"containing another quote\" end quote" goodbye将错误地使内部another quote与正则表达式匹配,因为字符串中剩余的引号数量为偶数。
总而言之
你真的需要所有的引号对都是格式良好的/匹配的,并且嵌套的引号要被转义,以便任何种类的正则表达式都能工作,不管是不是.NET引擎。
我建议使用@RicardoNolde从另一个问题(链接在上面)中的答案来删除所有引用的文本,然后匹配所有剩余的单词。
https://stackoverflow.com/questions/8966524
复制相似问题