Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 用正则表达式倒退_.net_Regex_Parsing_Comments_Key Value - Fatal编程技术网

.net 用正则表达式倒退

.net 用正则表达式倒退,.net,regex,parsing,comments,key-value,.net,Regex,Parsing,Comments,Key Value,我需要解析iOS的*.strings文件,以获得带有注释的键/值对。 例如: /* comment */ "key" = "value"; 一旦我找到了行并检查了它的有效性(我已经设法做到了),我就需要捕获它和它前面的注释 困难在于: 并非每一行之前都有注释,因此我无法捕获以/*开头并以分号结尾的整个块 下面可能有一行注释,但该行的格式可能无效,因此应将其与其注释一起跳过 因此,我必须检测键/值行,然后在它存在的情况下向上搜索注释 正则表达式可以倒转吗 另外,我正在使用.NET Frame

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

/* comment */
"key" = "value";
一旦我找到了行并检查了它的有效性(我已经设法做到了),我就需要捕获它和它前面的注释

困难在于:

  • 并非每一行之前都有注释,因此我无法捕获以/*开头并以分号结尾的整个块
  • 下面可能有一行注释,但该行的格式可能无效,因此应将其与其注释一起跳过
因此,我必须检测键/值行,然后在它存在的情况下向上搜索注释

正则表达式可以倒转吗

另外,我正在使用.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);
    }
}

您可以在单个正则表达式中完成所有这些操作:

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"];
Match=null;
匹配=正则表达式匹配(主题,

@(?正则表达式从不后退,即使您要执行类似于
+$
的操作。但是,您可以让它看起来像是在后退。但是,这并不是此任务真正需要的

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

/^(?<comment>(?:\/\*(?:(?!\*\/).)*\*\/)?\s*)(?<key>"(?:\\.|[^"])+")\s*=\s*(?<value>"(?:\\.|[^"])+")\s*;/gms
/^((?:\/*(?:(!\*/)***/)?\s*)(?“(?:\。[^])+”)\s*=\s*(?:\。[^])+”\s*/gms*
(不确定是否需要.net中的分隔符和全局标志)

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

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

演示+解释:


如果有什么不清楚的地方,可以提问。

您甚至可以将搜索的起点设置为从see:RegexOptions向后看。right to left

注释是否可以超过一行?理论上-是的,但我从未发现过。在多行注释的情况下,我可以使用string text=File.ReadAllText(文件名);但我无法想象在这种情况下如何找到所有匹配项。如果按行阅读,为什么不匹配
\”(\w+)“=\”(\w+)“=\”(\w+)“
,并提取捕获组?如果您使用自动解释这些正则表达式,您将节省大量时间:)@Lindrian:不起作用:正则表达式引擎不支持可变长度的lookbehinds。此外,我发现这些机器生成的解释通常没有太大帮助…@Lindrian:关于正则表达式101的建议非常好!比桌面程序好得多!关于正则表达式本身:键和值可能包含转义字符:\”\=etc.@TimPietzcker:你是对的。它使用的PHP不支持可变长度lookbehinds。尽管如此,在我看来,它在解释正则表达式方面做得非常好。(解释它不会有任何问题,但由于它同时运行匹配,你会从PHP得到一个错误)@保罗:看看我的正则表达式,它处理转义值。