C# 正则表达式最大值和最小值之间的战斗

C# 正则表达式最大值和最小值之间的战斗,c#,regex,C#,Regex,您好,我有以下字符串的文件: string.Format("{0},{1}", "Having \"Two\" On The Same Line".Localize(), "Is Tricky For regex".Localize()); 我的目标是获得具有两个字符串的匹配集: 在同一行上有两个 这对正则表达式来说很棘手 我当前的正则表达式如下所示: private Regex CSharpShortRegex = new Regex("\"(?<constant>[^\"]

您好,我有以下字符串的文件:

string.Format("{0},{1}", "Having \"Two\" On The Same Line".Localize(), "Is Tricky For regex".Localize());
我的目标是获得具有两个字符串的匹配集:

  • 在同一行上有两个
  • 这对正则表达式来说很棘手
我当前的正则表达式如下所示:

private Regex CSharpShortRegex = new Regex("\"(?<constant>[^\"]+?)\".Localize\\(\\)");
更新: 我的原始答案(在水平规则下)有一个bug:正则表达式匹配器尝试从左到右的顺序进行替换。将
[^”]
作为第一个备选方案允许它使用反斜杠,但下一个要匹配的字符是引号,这会阻止匹配继续进行

不兼容注意:根据下面的模式,perl回溯到另一个备选方案(转义引号),并成功地为同一行有“两个”的
案例找到匹配项

修复方法是先尝试转义引号,然后尝试非引号:

var CSharpShortRegex =
  new Regex("\"(?<constant>(\\\\\"|[^\"])*)\"\\.Localize\\(\\)");
var CSharpShortRegex=
新正则表达式(“\”(?(\”[^\”])*)\“\。本地化(\)”;
或者,如果您更喜欢at字符串形式:

var CSharpShortRegex =
  new Regex(@"""(?<constant>(\\""|[^""])*)""\.Localize\(\)");
var CSharpShortRegex=
新正则表达式(@“)(?(\\”“\\\”[^”“])*)\.Localize\(\)”;

允许逃逸:

private Regex CSharpShortRegex =
  new Regex("\"(?<constant>([^\"]|\\\\\")*)\"\\.Localize\\(\\)");
private Regex CSharpShortRegex=
新的正则表达式(“\”(?([^\”])*)\“\。本地化\(\)”;
应用一级转义使模式更易于阅读,我们得到

"(?<constant>([^"]|\\")*)"\.Localize\(\)
“(?([^“]\\”*)”\.本地化\(\)

也就是说,字符串以
字符开头和结尾,两者之间的所有内容都是非引号或转义引号。

以下是您需要的正则表达式:

@"""(?<constant>(\\.|[^""])*)""\.Localize\(\)"
请注意,我使用了
@“…”
,以避免在正则表达式中转义反斜杠。我认为这使阅读更容易。

这本书对我来说很有用:

\"((?:[^\\"]|(?:\\\"))*)\"\.Localize\(\)
对带有各种转义引号的多个字符串进行测试

看来回答这个问题的大多数人都有相同的大致想法,所以让我来解释一下方法(在
s之后的注释):

对于C#,您需要两次避开斜杠(混乱):

马克正确地指出,除了引号外,这个字符与转义字符不匹配。所以这里有一个更好的版本:

\"((?:[^\\"]|(?:\\")|(?:\\.))*)\"\.Localize\(\)
以及它被大幅削减的等价物:

\"((?:[^\\\\\"]|(?:\\\\\")|(?:\\\\.))*)\"\\.Localize\\(\\)
工作方式相同,只是它有一个特殊情况,即如果遇到斜杠但它不能匹配
\“
,它只会使用斜杠和下面的字符并继续



仔细想想,最好在每个斜杠上使用两个字符,这实际上是Mark的答案,所以我不会重复。

看起来您正在尝试解析代码,因此一种方法可能是动态评估代码:

var cr = new CSharpCodeProvider().CompileAssemblyFromSource(
    new CompilerParameters { GenerateInMemory = true }, 
    "class x { public static string e() { return " + input + "}}");

var result = cr.CompiledAssembly.GetType("x")
    .GetMethod("e").Invoke(null, null) as string;
通过这种方式,您可以处理使用正则表达式极难处理的所有其他特殊情况(例如连接字符串或逐字字符串)。

new regex(@)(((([^@]^^^\n)”(?(((\\)|[^”“])*)|(@”“(((“\\)*)\s*。\s*。\s*本地化\s*(\s*)”,RegexOptions.Compiled);
new Regex(@"((([^@]|^|\n)""(?<constant>((\\.)|[^""])*)"")|(@""(?<constant>(""""|[^""])*)""))\s*\.\s*Localize\s*\(\s*\)", RegexOptions.Compiled);

处理简单字符串和@“”字符串。它还考虑转义序列。

您可以添加正向回溯(向后匹配)。您能指望“,”出现吗?您是否总是尝试匹配这样的行?不,有时字符串可能是单独的。您唯一能指望的是“某个字符串”。Localize()是的,这也是我们开始的地方,但它不起作用。它是从“同一行的两个短语”开始的,它漏掉了像“热辣辣辣”这样的一行完全。@ryber:帮我一个忙,确保你正确地记录了这个正则表达式,这样它的意思就完全清楚了。未来的开发人员最不需要的就是遇到一个未记录的凌乱正则表达式。对于任何包含转义序列“\n”或“s”的字符串,这对我来说都是失败的\\“,它不如其他一些解决方案干净,而且它省略了命名组。@马克:噢,快照,关于转义序列,你说得对。这应该不难改变。此外,添加命名组也很简单,因为已经有了一个合适的捕获组。请参阅我的更新。排除反斜杠和引号并仅允许转义引号将拒绝所有其他转义。您只需要排除引号,如@gbacon:您忘记了转义斜杠本身的情况:
string=“\\\”.Localize()
它不是有效的C文本,但您的正则表达式将接受它。
\"((?:[^\\\\\"]|(?:\\\\\"))*)\"\\.Localize\\(\\)
\"((?:[^\\"]|(?:\\")|(?:\\.))*)\"\.Localize\(\)
\"((?:[^\\\\\"]|(?:\\\\\")|(?:\\\\.))*)\"\\.Localize\\(\\)
var cr = new CSharpCodeProvider().CompileAssemblyFromSource(
    new CompilerParameters { GenerateInMemory = true }, 
    "class x { public static string e() { return " + input + "}}");

var result = cr.CompiledAssembly.GetType("x")
    .GetMethod("e").Invoke(null, null) as string;
new Regex(@"((([^@]|^|\n)""(?<constant>((\\.)|[^""])*)"")|(@""(?<constant>(""""|[^""])*)""))\s*\.\s*Localize\s*\(\s*\)", RegexOptions.Compiled);