为什么此正则表达式在以下代码的代码前添加许可证file.hpp
:
perl -i -0pe 's@(.*\n)*?#ifndef@//LICENSE#ifndef@' file.hpp
和:
# -0: reads the file into ram (changes file spereator)
# -p: reads line by line
# -e: command execution
# -i: modifiy input directly
file.hpp(带有Unicode BOM的UTF-8):
#ifndef GAGA
#define GAGA
asd
asd
#ifndef NDEBUG
结果是
LICENSE#ifndef NDEBUG
我不明白为什么非贪婪(.*\n)*?
匹配直到NDEBUG行?为什么?
为了使问题更容易重现,下面是一个测试案例,文件内容为字符串:
$_ = "\xef\xbb\xbf#ifndef GAGA\n#define GAGA\nasd\nasd\n#ifndef NDEBUG\n";
s@(.*\n)*?#ifndef@//LICENSE#ifndef@;
print $_
它输出以下内容:
//LICENSE#ifndef NDEBUG
表示正则表达式与字符串的大部分匹配: "\xef\xbb\xbf#ifndef GAGA\n#define GAGA\nasd\nasd\n#ifndef"
为什么要匹配而不是其他?首先,请注意,正则表达式不能仅"\xef\xbb\xbf#ifndef"
因为以下原因而匹配:
"\xef\xbb\xbf"
部分可以匹配。"\n"
其次,regexp会匹配以开头的长字符串,"\xef\xbb\xbf"
而不是稍后输入的一些较短的字符串,因为regexp倾向于将匹配开始于尽可能接近输入字符串开头的位置,并且此首选项要强于贪婪/不贪婪。任何单个的量词。如果在字符串开头找到匹配项,则regexp引擎不会继续查找。从字符串的后面开始,它将找不到其他可能的匹配项,从而使非贪婪的量词变得“更快乐”。
因此,总的来说,正则表达式以字符串的开头开始,尝试将非贪婪的括号组匹配0次,发现它不起作用,(因为"\xef"
不是"#"
),尝试将其匹配1次,找到那是行不通的(因为"#define"
is不是"#ifndef"
),依此类推,直到最终找到与它匹配4次的作品,然后停止。4是导致字符串开头匹配的非贪婪部分的最小重复次数。
对于处理UTF-8 BOM的诅咒,我的首选策略是在执行其他任何操作之前先将其剥离。
$_ = "\xef\xbb\xbf#ifndef GAGA\n#define GAGA\nasd\nasd\n#ifndef NDEBUG\n";
s/^\xef\xbb\xbf//;
s@(.*\n)*?#ifndef@//LICENSE#ifndef@;
print $_
您可以将这些替换合并到一个操作中,但是我喜欢简单的方法,s/^\xef\xbb\xbf//;
因为我可以将其放入几乎任何脚本中-几乎在任何行上!-最坏的情况是什么也没有做,最多只能修复错误。
旁注:您应使用-0777
全文件格式。-0
单独将分隔符更改为,"\0"
如果文件包含NUL,它将不会执行您想要的操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句