正则表达式忽略了评论

时间:2009-10-12 01:11:03

标签: regex

作为一名正则表达式初学者,我需要一些帮助来编写正则表达式。它应该匹配一个特定的模式,让我们说“ABC”。但是在评论中使用时,模式不应该匹配('作为评论标志)。所以XYZ ' ABC 不应该匹配。 x("teststring ABC")也不应该匹配。但是ABC("teststring ' xxx")必须匹配结束,即xxx不会被切断。 也有人知道你可以用来“调试”正则表达式的免费Regex应用程序吗?我经常在识别我的尝试错误时遇到问题。谢谢!

10 个答案:

答案 0 :(得分:5)

有些人会发誓RegexBuddy。我从来没有使用过调试器,但我建议你避开它提供的正则表达式生成器。这只是个坏主意。

你可以用你正在使用的正则表达式来解决这个问题,但总的来说,我认为你会发现以“硬”的方式做到这一点更容易,也更容易维护。正则表达式适用于常规语言,嵌套任何东西通常意味着正则表达式不是一个好主意。对正则表达式语法的现代扩展意味着它可能是可行的,但它不会很漂亮,你肯定不会记得早上发生的事情。正则表达式失败的地方(即使使用现代非常规扩展)正在解析嵌套结构 - 尝试解析任何混合注释,引用字符串和括号很快就会变成一个难以理解且无法维护的混乱。不要误会我的意思 - 我喜欢在正确的地方使用正则表达式。这不是其中之一。

答案 1 :(得分:4)

关于好的正则表达式工具的主题,我真的很喜欢RegexBuddy,但它不是免费的。

除此之外,如果您需要检查内部字符串分隔符以及所有类别,则正则表达式是该作业的错误工具。您需要finite-state machine

答案 2 :(得分:4)

很多人推荐他们最喜欢的工具,但没有人提供解决方案。 (我是RegexBuddy的开发者,所以我不会推荐任何工具。)

没有好的方法来匹配Y,除非它是XYZ的一部分,只有一个正则表达式。你可以做的是写一个匹配Y和XYZ的正则表达式:Y | XYZ。然后使用一些额外的代码来处理Y的匹配,并忽略XYZ的匹配。一种方法是使用捕获组:(Y)| XYZ。现在您可以处理第一个捕获组的匹配项。当XYZ匹配时,捕获组与任何内容都不匹配。

要为VB样式的注释执行此操作,可以使用正则表达式:

'.*|(ABC)

此正则表达式匹配单引号和直到行尾的所有内容,或ABC。此正则表达式将匹配所有注释(无论是否包括ABC)。捕获组将匹配所有出现的ABC,除了评论中的那些。

如果您希望正则表达式都跳过注释和字符串,可以在正则表达式中添加字符串:

'.*|"[^"\r\n]*"|(ABC)

答案 3 :(得分:1)

我发现正则表达式最好的“调试器”只是在交互式环境中乱搞,尝试了很多小的问题。对于Python,ipython很棒;对于Ruby,irb,对于命令行类型的东西,sed ...

一次尝试一些小块,确保你理解它们,然后再添加一点点。冲洗并重复。

答案 4 :(得分:1)

对于.NET开发,你也可以尝试RegexDesigner,这个工具可以为你生成代码(VB / C#)。对于我们的Regex初学者来说,这是一个非常好的工具。

link text

答案 5 :(得分:1)

以下是我对此问题的解决方案: 1.在哈希中查找商店的所有评论 2.进行正则表达式替换 3.将评论带回文件

节省您的时间: - )

string fileTextWithComments = "Some tetx file contents";

Dictionary<string, string> comments = new Dictionary<string, string>();

// 1. Find a store all your comments in hash
Regex rc = new Regex("(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)");
MatchCollection matches = rc.Matches(fileTextWithComments);

int index = 0;
foreach (Match match in matches)
{
    string key = string.Format("/*Comment#{0}*/", index++);
    comments.Add(key, match.Value);
    fileTextWithComments = fileTextWithComments.Replace(match.Value, key);
}

// 2. Do your regexp replacement
Regex r = new Regex("YOUR REGEXP PATTERN");
fileTextWithComments = r.Replace(fileTextWithComments, "NEW STRING");


// 3. Bring comments back to file :-)
foreach (string key in comments.Keys)
{
    string comment = comments[key];
    fileTextWithComments = fileTextWithComments.Replace(key, comment);
}

答案 6 :(得分:0)

你可以澄清一下吗?我读了三遍,我认为你想要一个给定的模式,当它看起来像一个文字时。不作为评论或字符串的一部分。

作为一个正则表达式,你要求的是非常棘手的。因为你想跳过字符串。一行中的多个字符串会使问题复杂化。

我甚至不会尝试在一个正则表达式中执行此操作。相反,我首先通过过滤器传递每一行,删除字符串,然后按顺序发表评论。然后尝试匹配你的模式。

在Perl中,因为它具有正则表达式处理能力。假设@lines是您要匹配的行列表,$ pattern是您要匹配的模式。

@matches =[];
for (@lines){
  $line = $_;
  $line ~= s/"[^"]*?(?<!\)"//g;
  $line ~= s/'.*//g;
  push @matches, $_ if $line ~= m/$pattern/;
}

第一个替换找到任何以双引号开头并以第一个未转义的双引号结束的模式。使用退格的标准转义字符。 接下来剥离评论。如果模式仍匹配,则将该行添加到匹配列表中。

它并不完美,因为它无法区分"a\\""a\"之间的区别。第一个通常是有效的字符串,后者则不是。无论哪种方式,这些替换将继续寻找另一个“,如果没有找到一个字符串没有被抛出。我们可以使用另一个替换来用其他东西替换所有双反斜杠。但是这会导致问题,如果模式你'重新寻找包含反斜杠。

答案 7 :(得分:0)

如果您只有单行注释,则可以使用zero width look-behind assertion,但如果您使用的是多行注释,则会变得有点棘手。

最终,你真的需要用某种解析器解决这类问题,因为注释的定义实际上是由语法驱动的。

This answer一个不同但相关的问题看起来也很好......

答案 8 :(得分:0)

如果您有Emacs,则有一个名为“regexp-builder”的内置正则表达式工具。我不太了解你的正则表达式问题的具体细节,足以提出答案。

答案 9 :(得分:0)

RegEx1:(-user ")(.*?)"

主题:报告-user&#34;测试用户&#34; -date 1/4/13 -day monday -daterange&#34; 1/4/13 1/20/13&#34; -

结果:-user "test user"

Regex2:(-daterange ")(.*?)"

主题:报告-user&#34;测试用户&#34; -date 1/4/13 -day monday -daterange&#34; 1/4/13 1/20/13&#34; -

结果:-daterange "1/4/13 1/20/13"

RegEx3:(-date )(.*?)( -)

主题:报告-user&#34;测试用户&#34; -date 1/4/13 -day monday -daterange&#34; 1/4/13 1/20/13&#34; -

结果:-date 1/4/13 -

RegEx4:(-day )(.*?)( -)

主题:报告-user&#34;测试用户&#34; -date 1/4/13 -day monday -daterange&#34; 1/4/13 1/20/13&#34; -

结果:-day monday -

如果未找到,首先搜索引用值,搜索无引号参数。这只需要出现一次参数。它也期望命令要么;使用引号来封装一个没有引号的字符串,或;在第一个位置使用除引号之外的任何字符,不会出现&#39; - &#39;直到下一个参数,并有一个尾随&#39; - &#39; (在正则表达式之前将其添加到字符串中)。