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