Perl正则表达式意外地用“g”选项替换运行两次

时间:2013-04-15 17:15:47

标签: regex perl bash

所以我有一个包含更多文件夹的文件夹。我想告诉一个朋友,他们应该,而不是每个文件夹都有源文件,只有源文件,每个文件都有多个功能;

即。而不是这个:

src/
    load_of_functions/
        function1.py
        function2.py
        function3.py
        function4.py
    load_more_functions/
        function5.py
        function6.py
        function7.py
    even_more_funcitons/
        function9.py
        function10.py

他们应该有这个:

src/
    load_of_functions.py
    load_more_functions.py
    even_more_funcitons.py

所以我进入了目录,并做了一个小小的班轮,以获取要发送电子邮件的目录名称;

$ ls -l | grep ^d | awk '{print $9}' | perl -pe 's/(.*)/\1.py/g'

ls -l获取文件和所有信息 grep ^d只保留dirs awk '{print $9}'只打印第9列 - 即dir名称 并perl -pe 's/(.*)/\1.py/g'向每行添加“.py”。

当我这样做时,我明白了:

$ ls -l | grep ^d | awk '{print $9}' | perl -pe 's/(.*)/\1.py/g'
1.py.py
10.py.py
2.py.py
3.py.py
4.py.py
5.py.py
6.py.py
7.py.py
8.py.py
9.py.py

我知道我没有解析文件,而是逐行执行,因此不需要全局g。所以我把它拿出来,它工作正常。

这很好。

但是当我把g放进去的时候,为什么要做两次替换呢?这对我没有意义!

1 个答案:

答案 0 :(得分:4)

.*匹配零个或多个字符,这意味着它可以匹配零个字符。

假设你有

$_ = 'abc';
s/(.*)/\1.py/g;

第一次搜索匹配时,它匹配substr($_,0,3),然后/g会导致它检查从pos 3或更高版本开始的另一场比赛。

第二次搜索匹配时,它匹配substr($_,3,0),然后/g会导致它检查从pos 3或更高版本开始的另一场比赛。

第三次搜索匹配项时,它匹配substr($_,3,0)。但是,引擎拒绝匹配相同的子字符串(定义为具有相同的起始位置和相同的长度)两次,因此它失败。

解决方案:

s/(.*)/\1.py/;    # Poor
s/^(.*)/\1.py/g;  # Poor
s/^(.*)/\1.py/;   # Ok
s/$/.py/;         # Better
$_ .= '.py';      # Best if -l was present