1

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

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

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

困难在于:

  • 并非每一行之前都有注释,因此我无法捕获以 /* 开头并以分号结尾的整个块;
  • 可能有下面一行的注释,但该行的格式可能无效,因此它应该连同它的注释一起被跳过。

所以我必须检测键/值行,然后如果存在就上去评论。

正则表达式可以倒退吗?

PS我正在使用.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);
    }
}
4

3 回答 3

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"];
于 2012-12-21T12:55:55.107 回答
0

正则表达式永远不会倒退,即使您要执行类似.+$. 但是你可以让它看起来好像它们是向后工作的。但是,这对于此任务并不是真正必要的。

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

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

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

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

您现在拥有所需的所有数据。只需相应地更换。如果第一个反向引用包含一个null值,您就知道该行上方没有注释。

演示+说明:http ://regex101.com/r/xN1uQ4

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

于 2012-12-21T12:59:00.603 回答
0

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

于 2018-07-07T14:15:15.733 回答