添加Perl脚本的代码行只修改一个文件



我有这个:

perl -pi -e 'print "code I want to insertn" if $. == 2' *.php

code I want to insert行放在文件的第二行,这是我需要对每个PHP文件

所做的

如果我在包含PHP文件和非PHP文件的目录中运行它,它会做正确的事情,但只对一个PHP文件。我以为*.php会将它应用于所有PHP文件,但它没有这样做。

我怎么写它,它会修改每个PHP文件在一个目录?如果有一种简单的方法可以递归地遍历所有目录,那就更好了。我不介意为每个目录运行Perl脚本,因为没有那么多,但不想手工编辑每个文件。

问题是Perl用于读取命令行上传递的文件的文件句柄ARGV从未显式关闭,因此行号$.只是在第一个文件结束后保持递增,并且永远不会返回到1。

通过关闭ARGV来修复这个问题,当它到达文件结束时。Perl将重新打开它以读取列表中的下一个文件,因此重置$.

perl -i -pe 'print "code I want to insertn" if $. == 2; close ARGV if eof' *.php

如果您可以使用sed,这应该可以工作:

sed -si '2iCODE YOU WANT TO INSERT' *.php

要递归地执行,可以尝试:

find -name '*.php' -execdir sed -si '2iCODE YOU WANT TO INSERT' '{}' +

使用File::Find .

注意,我已经包含了3个完整性检查来验证事情实际上是按照你想要的方式处理的。

  1. 一开始脚本只会打印出找到的文件,直到你注释掉所有的返回。
  2. 脚本将保存备份,除非你取消unlink语句的注释。
  3. 最后,脚本将只处理一个文件,直到注释掉exit语句。

这三个检查只是为了在编辑整个目录树之前验证一切是否如您所愿。

use strict;
use warnings;
use File::Find;
my $to_insert = "code I want to insertn";
find(sub {
    return unless -f && /.php$/;
    print "Edit $File::Find::namen";
    return; # Comment out once satisfied with found files
    local $^I = '.bak';
    local @ARGV = $_;
    while (<>) {
        print $to_insert if $. == 2 && $_ ne $to_insert;
        print;
    }
    # unlink "$_$^I"; # Uncomment to delete backups once certain that first file is processed correctly.
    exit; # Comment out once certain that first file is processed correctly 
}, '.')

相关内容

最新更新