Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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
Regex perl正则表达式,ungreedy匹配不知何故不受尊重?_Regex_Perl - Fatal编程技术网

Regex perl正则表达式,ungreedy匹配不知何故不受尊重?

Regex perl正则表达式,ungreedy匹配不知何故不受尊重?,regex,perl,Regex,Perl,为什么此正则表达式要在文件.hpp中的代码前面添加许可证 perl -i -0pe 's@(.*\n)*?#ifndef@//LICENSE#ifndef@' file.hpp 与: file.hpp(带Unicode BOM的utf-8): 导致 LICENSE#ifndef NDEBUG 我不明白为什么非贪婪的(.*\n)*?匹配到行? 为什么?为了使问题更容易重现,下面是一个以字符串形式显示文件内容的测试用例: $_ = "\xef\xbb\xbf#ifndef GAGA\n#defi

为什么此正则表达式要在
文件.hpp
中的代码前面添加许可证

perl -i -0pe 's@(.*\n)*?#ifndef@//LICENSE#ifndef@' file.hpp
与:

file.hpp(带Unicode BOM的utf-8):

导致

LICENSE#ifndef NDEBUG
我不明白为什么非贪婪的
(.*\n)*?
匹配到行?
为什么?

为了使问题更容易重现,下面是一个以字符串形式显示文件内容的测试用例:

$_ = "\xef\xbb\xbf#ifndef GAGA\n#define GAGA\nasd\nasd\n#ifndef NDEBUG\n";
s@(.*\n)*?#ifndef@//LICENSE#ifndef@;
print $_
它的输出是:

//LICENSE#ifndef NDEBUG
表示regexp与字符串的大部分匹配:
“\xef\xbb\xbf\ifndef GAGA\n\define GAGA\nasd\n\ifndef”

为什么是那场比赛而不是其他比赛?首先,请注意regexp不能仅匹配
“\xef\xbb\xbf\ifndef”
,因为:

  • 如果括号中的组匹配0次,则没有任何内容可以匹配
    “\xef\xbb\xbf”
    部分
  • 如果括号中的组至少匹配1次,则匹配必须包括一个
    “\n”
其次,regexp匹配以
开头的长字符串“\xef\xbb\xbf”
而不是输入中稍后开始的某个较短字符串,因为regexp更喜欢在尽可能靠近输入字符串开头的地方开始匹配,并且该首选项比任何单个量词的贪婪性/非贪婪性强。如果在字符串开头找到匹配项,则regexp引擎不会继续查找。它不会找到另一个可能的匹配项,从字符串的后面开始,使非贪婪量词“更快乐”

因此,总体而言,regexp从字符串的开头开始,尝试匹配非贪婪的括号组0次,发现它不起作用(因为
“\xef”
不是
“#”
),尝试匹配它1次,发现不起作用(因为
“#define”
不是
“#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/因为我可以在几乎任何一行将其放入任何脚本中最坏的情况下,它什么也不做,最多只能修复一个bug


旁注:您应该使用
-0777
进行整个文件的slurping
-0
单独将分隔符更改为
“\0”
,这样,如果文件包含NUL,它就不会执行您想要的操作。

为了使问题更容易重现,下面是一个将文件内容作为字符串的测试用例:

$_ = "\xef\xbb\xbf#ifndef GAGA\n#define GAGA\nasd\nasd\n#ifndef NDEBUG\n";
s@(.*\n)*?#ifndef@//LICENSE#ifndef@;
print $_
它的输出是:

//LICENSE#ifndef NDEBUG
表示regexp与字符串的大部分匹配:
“\xef\xbb\xbf\ifndef GAGA\n\define GAGA\nasd\n\ifndef”

为什么是那场比赛而不是其他比赛?首先,请注意regexp不能仅匹配
“\xef\xbb\xbf\ifndef”
,因为:

  • 如果括号中的组匹配0次,则没有任何内容可以匹配
    “\xef\xbb\xbf”
    部分
  • 如果括号中的组至少匹配1次,则匹配必须包括一个
    “\n”
其次,regexp匹配以
开头的长字符串“\xef\xbb\xbf”
而不是输入中稍后开始的某个较短字符串,因为regexp更喜欢在尽可能靠近输入字符串开头的地方开始匹配,并且该首选项比任何单个量词的贪婪性/非贪婪性强。如果在字符串开头找到匹配项,则regexp引擎不会继续查找。它不会找到另一个可能的匹配项,从字符串的后面开始,使非贪婪量词“更快乐”

因此,总体而言,regexp从字符串的开头开始,尝试匹配非贪婪的括号组0次,发现它不起作用(因为
“\xef”
不是
“#”
),尝试匹配它1次,发现不起作用(因为
“#define”
不是
“#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/因为我可以在几乎任何一行将其放入任何脚本中最坏的情况下,它什么也不做,最多只能修复一个bug


旁注:您应该使用
-0777
进行整个文件的slurping
-0
单独将分隔符更改为
“\0”
,这样,如果文件包含NUL,它就不会执行您想要的操作。

我尝试时不会这样做。我的文件的第一行是
//LICENSE#ifndef GAGA
。您确定您的
文件.hpp
仍然是原始文件吗?(也就是说,您还没有使用Perl就地修改使用垃圾对其进行修改吗?)此外,您的结果缺少
/
之前的
许可证
。这会让你烦恼吗?这很奇怪:当
file.hpp
的编码是UTF8和Unicode BOM时,就会发生这种情况。(当我这样做时,上面的内容适用)有人知道问题是什么吗?Re“-0:将文件读入ram”,这不是
-0
所做的。这就是
-0777
所做的,这是应该使用的。当我尝试时,它不会。我的文件的第一行是
//LICENSE#ifndef GAGA
。您确定您的
文件.hpp
仍然是原始文件吗?(也就是说,您还没有使用Perl就地修改使用垃圾对其进行修改?)