【发布时间】:2009-06-04 23:30:06
【问题描述】:
我正在开发一个分析 DSL 的预处理器。我的目标是删除 cmets。
块注释功能由%% 前后划分。根据语言的定义,我不必担心 %% 在字符串中。
我正在使用这个s/// 正则表达式。不幸的是,它似乎匹配了所有东西并消灭了它:
#Remove multiline comments.
$text_string =~ s/%%.*%%//msg;
我做错了什么?
【问题讨论】:
我正在开发一个分析 DSL 的预处理器。我的目标是删除 cmets。
块注释功能由%% 前后划分。根据语言的定义,我不必担心 %% 在字符串中。
我正在使用这个s/// 正则表达式。不幸的是,它似乎匹配了所有东西并消灭了它:
#Remove multiline comments.
$text_string =~ s/%%.*%%//msg;
我做错了什么?
【问题讨论】:
你可以做的第一件事就是让它不贪婪:
.*?
否则,
%% 一些文字 %%
真实内容
%% 其他文字 %%
都将被消灭。
【讨论】:
来自perlfaq6: What does it mean that regexes are greedy? How can I get around it?
大多数人的意思是贪婪的正则表达式尽可能匹配。从技术上讲,实际上是量词(?、*、+、{})是贪婪的,而不是整个模式; Perl 更喜欢局部的贪婪和即时的满足,而不是整体的贪婪。要获得相同量词的非贪婪版本,请使用 (??, *?, +?, {}?)。
一个例子:
$s1 = $s2 = "I am very very cold";
$s1 =~ s/ve.*y //; # I am cold
$s2 =~ s/ve.*?y //; # I am very cold
注意第二个替换是如何在遇到“y”时停止匹配的。这 *?量词有效地告诉正则表达式引擎尽快找到匹配项并将控制权传递给下一行,就像你在玩烫手山芋一样。
【讨论】:
假设您已将整个代码读入变量 $str 并且在 %% 和 %% 之间不可能出现单个 %,您可以使用它。
$str =~s/%%([^%]+)%%//g;
【讨论】: