我正在尝试创建一种模式,该模式以“ WORD”开头,并匹配除原始“ WORD”以外的所有字母,数字和字符,直到出现“ ENDWORD”为止。
在此示例中,我希望它与第二个出现的“ WORD”匹配并匹配到“ ENDWORD”;但是,它是从第一次出现开始,并没有正确排除第二次出现的“ WORD”。
似乎the俩与“ WORD”以外的任何字符都匹配。下面的示例使用否定的超前查询,该查询被前面的“。”否定。 (任意),但我不确定如何将肯定的“任意”或换行符与否定词组合在一起。任何帮助将不胜感激。
这是我在LinqPad中运行的示例c#程序。
void Main() {
var text =
@"WORD
[asdf] ---
123/\*&
WORD
[asdf] ---
123/\*&
ENDWORD
[asdf] ---
123/\*&";
var pattern = $"(WORD).|\\n\\b(?!WORD)\\b.|\\n*(ENDWORD)";
Regex rgx = new Regex(pattern);
foreach (Match match in rgx.Matches(text))
{
match.Dump();
}
}
说明问题的另一种方法是从“ ENDWORD”开始(捕获它),回溯,忽略所有字符,直到找到“ WORD”的第一个出现并捕获它。只是为了澄清“ ENDWORD”而不是字符串的末尾而修改。
答案 0 :(得分:1)
从结尾开始那将是一个非贪婪的正则表达式:
编辑:忘记了“。”包括所有字符,但不包括换行符。
"WORD(\n|.)+?ENDTHING"
带有RightToLeft
选项:
Regex.Matches(input, pattern, RegexOptions.RightToLeft)
我用您在https://rextester.com/tester上输入的文字对它进行了测试
答案 1 :(得分:1)
对于示例数据,您可以首先匹配WORD
,后跟空格或制表符。然后重复匹配不包含WORD的行,直到遇到一行包含ENDWORD
并由空格或制表符开头的行。
要检查该行是否不包含WORD,可以使用否定的前行。
[ \t]WORD\b.*(?:\r?\n(?!.*[ \t](?:END)?WORD\b).*)*\r?\n[ \t]+ENDWORD\b
说明
[ \t]
匹配空格或制表符WORD\b
匹配单词和单词边界.*
匹配除换行符外的所有char 0次以上(?:
非捕获组
\r?\n(?!.*[ \t](?:END)?WORD\b)
重复0+次,该行不包含可选END,后跟WORD .*
如果是这种情况,则匹配整行)*
关闭非捕获组并重复0次以上\r?\n[ \t]+ENDWORD\b
将换行符,1个以上的空格或制表符和ENDWORD与单词边界匹配例如:
var pattern = @"[ \t]WORD\b.*(?:\r?\n(?!.*[ \t](?:END)?WORD\b).*)*\r?\n[ \t]+ENDWORD\b";
答案 2 :(得分:0)
我喜欢简单的解决方案
var result = text.Substring(0, text.LastIndexOf("ENDWORD")).Split(new[] {"WORD"},StringSplitOptions.None);
答案 3 :(得分:0)
进一步研究之后,似乎有一个更简单的解决方案。我可能在我的问题中引起了一些困惑,因为WORD和ENDWORD之间除了位置没有关系。这是简化的模式和示例。
void Main()
{
var text =
@"WORD
[asdf] ---
123/\*&
WORD
[asdf] ---
123/\*&
ENDTHING
[asdf] ---
123/\*&";
var pattern = $"(WORD)(?:(?!WORD\\b).|\\n)*(ENDTHING)";
Regex rgx = new Regex(pattern);
foreach (Match match in rgx.Matches(text))
{
match.Dump();
}
}