与RegEx一起倒退

时间:2012-12-21 12:44:45

标签: .net regex parsing comments key-value

我需要解析iOS的* .strings文件以获得带注释的键/值对。 例如:

/* comment */
"key" = "value";

一旦我找到了这条线并检查了它的有效性(我已经设法做到了),我需要捕捉它并在它之前发表评论。

困难在于:

  • 以前不是每一行都有注释,所以我无法捕获以/ *开头并以分号结尾的整个块;
  • 下面的行可能会有评论,但此行格式可能无效,因此可以跳过评论。

所以我必须检测键/值行,如果存在,则进行评论。

RegEx'es可以倒退吗?

P.S。我正在使用.NET Framework来解析:

string[] lines = File.ReadAllLines(fileName);
foreach (string line in lines)
{
    string[] kvp = Regex.Split(line, "\"\\s+?=\\s+?\"");
    if (kvp.Length == 2 && kvp[0].StartsWith("\"") && kvp[1].EndsWith("\";"))
    {
        DataRow row = table.NewRow();
        row["name"] = kvp[0].TrimStart('"');
        row["text"] = kvp[1].Substring(0, kvp[1].Length - 2);
        row["fileId"] = fileId;
        table.Rows.Add(row);
    }
}

3 个答案:

答案 0 :(得分:3)

你可以在一个正则表达式中完成所有这些:

Match match = null;
match = Regex.Match(subject, 
    @"(?<=           # Look behind to make sure that there is a comment before:
    (?:              # Try to match...
     /\*             # /*
     (?<comment>     # Capture the comment in the group 'comment'
      (?:            # Match...
       (?!\*/)       # (as long as it's not '*/')
       .             # any character.
      )*             # Repeat as needed.
     )               # End of group 'comment'
     \*/             # Match */
    )?               # Make the whlo comment optional
     \s*             # Match whitespace, including newlines
    )                # End of lookbehind assertion
    ^                # Match the start of the line
    ""               # Match a quote
    (?<name>[^""]*)  # Capture any number of non-quote characters into group 'name'
    ""\s*=\s*""      # Match quote - equals - quote, with optional whitespace
    (?<value>[^""]*) # Capture any number of non-quote characters into group 'text'
    "";              # Match the closing quote and semicolon", 
    RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
row["name"] = match.Groups["name"];
row["text"] = match.Groups["text"];
row["comment"] = match.Groups["comment"];

答案 1 :(得分:0)

即使您要执行.+$之类的操作,正则表达式也不会倒退。但是你可以让它看起来像是倒退了。但是,这对于此任务来说并不是必需的。

您可以使用以下正则表达式:

/^(?<comment>(?:\/\*(?:(?!\*\/).)*\*\/)?\s*)(?<key>"(?:\\.|[^"])+")\s*=\s*(?<value>"(?:\\.|[^"])+")\s*;/gms

(不确定你是否需要分隔符和.net中的全局标志)

所以基本上,第一次反向引用将持有评论。第二个将持有密钥,第三个将持有该值。如果你对键/值不感兴趣,可以通过将最后两个反向引用合并为一个来进一步简化正则表达式。

您现在拥有了所需的所有数据。只需更换。如果第一个反向引用包含null值,则表示该行上方没有注释。

演示+解释:http://regex101.com/r/xN1uQ4

询问是否有任何不清楚的地方。

答案 2 :(得分:0)

甚至可以将搜索的起点设置为向后看,例如:RegexOptions.RightToLeft