C# 正则表达式标记化问题
我有用户输入的字符串,并希望标记它们。为此,我想使用正则表达式,现在有一个特殊情况的问题。 一个示例字符串是C# 正则表达式标记化问题,c#,regex,tokenize,C#,Regex,Tokenize,我有用户输入的字符串,并希望标记它们。为此,我想使用正则表达式,现在有一个特殊情况的问题。 一个示例字符串是 Test+“Hello”+“Good\”more“+“Escape\”This\“Test” 或者C#等价物 @“Test+”“Hello”“+”“Good\”“more”“+”“Escape\”“This\”“Test”“” 我能够匹配测试和+标记,但不能匹配“测试”中包含的标记。我使用“让用户指定这实际上是一个字符串,而不是一个特殊的标记。现在,如果用户想在字符串中使用”字符,我想允
Test+“Hello”+“Good\”more“+“Escape\”This\“Test”
或者C#等价物
@“Test+”“Hello”“+”“Good\”“more”“+”“Escape\”“This\”“Test”“”
我能够匹配测试
和+
标记,但不能匹配“测试”中包含的标记。我使用“让用户指定这实际上是一个字符串,而不是一个特殊的标记。现在,如果用户想在字符串中使用”字符,我想允许他用\来转义它
所以规则是:给我两个“”之间的所有字符,但最后一个“不能是\”前面的字符
我期望的结果是:“Hello”
“Good\”more““Escape\”这个“测试”
我需要在最终匹配中使用“”字符,这样我就知道这是一个字符串
我目前有一个regex@”“([\w]*)(?它给出了以下结果:“Hello”
所以后面的查找没有按我所希望的那样工作。有人知道获得我想要的字符串的正确方法吗?下面是我用来解析命令行的正则表达式的一个改编:
(?!\+)((?:"(?:\\"|[^"])*"?|\S)+)
范例
(自适应是指忽略+
并检查\“
而不是”
)的消极前瞻性操作)
希望这对你有帮助
问候
编辑:
如果您对周围的引号不感兴趣:
(?!\+)(?:"((?:\\"|[^"])*)"?|(\S+))
为了更安全,我建议使用以下正则表达式获取“…”
的未替换对中的所有子字符串:
^(?:[^"\\]*(?:\\.[^"\\]*)*("[^"\\]*(?:\\.[^"\\]*)*"))+
相配
^
-字符串的开头(以便我们可以检查每个“
和转义序列)
(?:
-非捕获组1用作后续子模式的容器
[^“\\]*(?:\..^“\\]*)*
-匹配0+字符,而不是”
和\
,后跟0+序列的\.
(任何转义序列),后跟0+字符,而不是“
和\
(因此,我们避免匹配第一个”
这是转义的,它前面可以有任意数量的转义序列)
(“[^”\\]*(?:\.[^”\]*)*”
-捕获组1中匹配的“…”
子字符串,其中可能包含任何转义序列
)+
-重复1次或多次的第一个非捕获组的结束
请参阅,这里是一个:
var rx=“^(?:[^\“\\\\]*(?:\\\\..^\\\\]*)*(\“[^\\\\\]*(?:\\\\\.^\\\\\]*)*)+”;
var s=@“Test+”“Hello”“+”“Good\”“more”“+\”“Escape\”“This\”“Test\”“f”“;
var matches=正则表达式匹配(s,rx)
.Cast()
.SelectMany(m=>m.Groups[1]。Captures.Cast().Select(p=>p.Value.ToArray())
.ToList();
Console.WriteLine(string.Join(“\n”,匹配项));
更新
如果需要删除令牌,只需使用以下代码匹配并捕获它们之外的所有令牌:
var keep = "[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*";
var rx = string.Format("^(?:(?<keep>{0})\"{0}\")+(?<keep>{0})$", keep);
var s = @"Test + ""Hello"" + ""Good\""more"" + \""Escape\""This\""Test\"" + ""f""";
var matches = Regex.Matches(s, rx)
.Cast<Match>()
.SelectMany(m => m.Groups["keep"].Captures.Cast<Capture>().Select(p => p.Value).ToArray())
.ToList();
Console.WriteLine(string.Join("", matches));
var keep=“[^\”\\\]*(?:\\\\\.[^\“\\\\]*)*”;
var rx=string.Format(“^(?({0})\{0}\”+({0})$”,保留);
var s=@“Test+”“Hello”“+”“Good\”“more”“+\”“Escape\”“This\”“Test\”“f”“;
var matches=正则表达式匹配(s,rx)
.Cast()
.SelectMany(m=>m.Groups[“keep”].Captures.Cast().Select(p=>p.Value.ToArray())
.ToList();
Console.WriteLine(string.Join(“,matches));
看
输出:Test++\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/code>好\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\。这甚至会匹配。这看起来很好。但是,对于标记化,我想用空字符串替换输入字符串中的匹配项,因为我有多个用于不同目的的表达式。您的正则表达式将整个字符串作为匹配项提供给我,那么删除匹配项的最安全方法是什么?我可以替换第一次出现的eac正则表达式找到的字符串的h,但我想知道这是否是一种安全的方法。好的,那么您需要删除“Hello”
,“Good\”more“
,以及“f”
,对吗?让我检查一下。。。
var keep = "[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*";
var rx = string.Format("^(?:(?<keep>{0})\"{0}\")+(?<keep>{0})$", keep);
var s = @"Test + ""Hello"" + ""Good\""more"" + \""Escape\""This\""Test\"" + ""f""";
var matches = Regex.Matches(s, rx)
.Cast<Match>()
.SelectMany(m => m.Groups["keep"].Captures.Cast<Capture>().Select(p => p.Value).ToArray())
.ToList();
Console.WriteLine(string.Join("", matches));