代码之家  ›  专栏  ›  技术社区  ›  ryber

雷杰克斯最大值和最小值之间的战斗

  •  1
  • ryber  · 技术社区  · 15 年前

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

    string.Format("{0},{1}", "Having \"Two\" On The Same Line".Localize(), "Is Tricky For regex".Localize());
    

    我的目标是用这两个字符串建立一个匹配集:

    • 在同一行有“两个”
    • 对Regex来说很棘手

    我当前的regex如下:

    private Regex CSharpShortRegex = new Regex("\"(?<constant>[^\"]+?)\".Localize\\(\\)");
    

    我的问题是第一行中的转义引号,我最后停在了引号处,我得到:

    • 在同一条线上
    • 这种款式也很难

    然而,试图忽略转义引号是不可行的,因为它使regex贪婪,我得到

    • 将“two”放在同一行“.localize()”,对于regex来说很难操作。

    我们似乎被夹在最大和最小的咀嚼之间。有什么希望吗?我有一些后备计划。你能向后再生吗?这样做会更容易,因为我可以从“以斯拉科尔”开始。

    编辑: 澄清。这是我唯一的优势。大多数时候,字符串都是单独存在的,比如:

    var myString = "Hot Patootie".Localize()
    
    5 回复  |  直到 15 年前
        1
  •  1
  •   Welbog    15 年前

    这个适合我:

    \"((?:[^\\"]|(?:\\\"))*)\"\.Localize\(\)
    

    在测试 http://www.regexplanet.com/simple/index.html 对多个字符串使用不同的转义引号。

    看起来大多数回答这个问题的人都有同样的粗略想法,所以让我解释一下这个方法(后面的评论 # S):

    \"             # We're looking for a string delimited by quotation marks
    (              # Capture the contents of the quotation marks
      (?:          #   Start a non-capturing group
        [^\\"]     #     Either read a character that isn't a quote or a slash
        |(?:\\\")  #     Or read in a slash followed by a quote.
      )*           #   Keep reading
    )              # End the capturing group
    \"             # The string literal ends in a quotation mark
    \.Localize\(\) # and ends with the literal '.Localize()', escaping ., ( and )
    

    对于C你需要避开两次斜杠(凌乱):

    \"((?:[^\\\\\"]|(?:\\\\\"))*)\"\\.Localize\\(\\)
    

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

    \"((?:[^\\"]|(?:\\")|(?:\\.))*)\"\.Localize\(\)
    

    它的切割等效物:

    \"((?:[^\\\\\"]|(?:\\\\\")|(?:\\\\.))*)\"\\.Localize\\(\\)
    

    工作原理相同,但有一个特殊情况,即如果遇到斜线,但它不能匹配 \" 它只使用斜杠和下面的字符并继续。


    想想看,最好在每个斜线处使用两个字符,这是马克的答案,所以我不会重复。

        2
  •  1
  •   Mark Byers    15 年前

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

    @"""(?<constant>(\\.|[^""])*)""\.Localize\(\)"
    

    测试程序:

    使用系统; 使用System.Text.RegularExpressions; 使用system.io;

    class Program
    {
        static void Main()
        {
            Regex CSharpShortRegex =
                new Regex(@"""(?<constant>(\\.|[^""])*)""\.Localize\(\)");
    
            foreach (string line in File.ReadAllLines("input.txt"))
                foreach (Match match in CSharpShortRegex.Matches(line))
                    Console.WriteLine(match.Groups["constant"].Value);
        }
    }
    

    输出:

    Having \"Two\" On The Same Line
    Is Tricky For regex
    Hot Patootie
    

    注意我用过 @"..." 避免在正则表达式中转义反斜杠。我认为这使阅读更容易。

        3
  •  1
  •   Greg Bacon    15 年前

    更新:

    我的原始答案(在水平规则下面)有一个错误:正则表达式匹配器尝试从左到右的顺序替换。有 [^"] 因为第一个选项允许它使用反斜杠,但是接下来要匹配的字符是一个引号,这会阻止匹配继续进行。

    不相容性说明: 给定下面的模式,Perl将跟踪到另一个选项(转义引号),并成功地找到与 Having \"Two\" On The Same Line 案例。

    解决方法是先尝试转义引号,然后尝试非引号:

    var CSharpShortRegex =
      new Regex("\"(?<constant>(\\\\\"|[^\"])*)\"\\.Localize\\(\\)");
    

    或者,如果您喜欢at字符串形式:

    var CSharpShortRegex =
      new Regex(@"""(?<constant>(\\""|[^""])*)""\.Localize\(\)");
    

    允许逃逸:

    private Regex CSharpShortRegex =
      new Regex("\"(?<constant>([^\"]|\\\\\")*)\"\\.Localize\\(\\)");
    

    应用一级转义使模式更容易阅读,我们得到

    "(?<constant>([^"]|\\")*)"\.Localize\(\)
    

    也就是说,一个字符串的开头和结尾都是 " 字符,两者之间的任何内容都是非引号或转义引号。

        4
  •  0
  •   Josef Pfleger    15 年前

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

    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;
    

    通过这种方式,您可以处理其他各种特殊情况(例如,串联或逐字字符串),使用regex处理这些情况非常困难。

        5
  •  0
  •   vadim    15 年前
    new Regex(@"((([^@]|^|\n)""(?<constant>((\\.)|[^""])*)"")|(@""(?<constant>(""""|[^""])*)""))\s*\.\s*Localize\s*\(\s*\)", RegexOptions.Compiled);
    

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