perl -pi -e究竟是做什么的?

时间:2015-01-24 23:36:16

标签: perl

我想知道Perl在使用选项perl -pi -e执行时运行的等效代码是什么?

在某些问题上我可以读到这个:

while (<>) {
    ...     # your script goes here
} continue {
    print;
}

但是此示例未显示保存文件的部分。

Perl如何确定EOL?没有发生任何变化时是否触摸文件?例如,如果我有一个旧的MAC文件(仅\r)。它如何处理s/^foo/bar/gm

我尝试使用Perl调试器但它并没有真正帮助。所以我只想猜测:

#!/usr/bin/env perl

my $pattern = shift;
map &process, @ARGV;
# perl -pi -e PATTERN <files>...
sub process {
    next unless -f;
    open my $fh, '<', $_;
    my $extract;
    read $fh, $extract, 1024;
    seek &fh, 0, 0;
    if ($extract =~ /\r\n/) {
        $/ = "\r\n";
    } elsif ($extract =~ /\r[^\n]/) {
        $/ = "\r";
    } else {
        $/ = "\n";
    }

    my $out = '';
    while(<&fh>) {
        my $__ = $_;

        eval $pattern;

        my $changes = 1 if $_ ne $__;
        $out .= $_;
    }

    if($changes)
    {
        open my $fh, '>', $_;
        print $fh $out;
    }
    close &fh;
}

2 个答案:

答案 0 :(得分:8)

您可以使用核心模块B :: Deparse检查Perl实际使用的代码。使用选项-MO=Deparse激活此编译器后端模块。

$ perl -MO=Deparse -p -i -e 's/X/U/' ./*.txt
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/X/U/;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

因此perl循环遍历给定文件中的行,执行代码并将$ _设置为行并打印结果$ _。

魔法变量$ ^ I被设置为空字符串。这将在现场编辑。就地编辑在perldoc perlrun中进行了解释。没有检查文件是否未更改。因此,始终更新编辑文件的修改时间。显然,备份文件的修改时间与原始文件的修改时间相同。

使用-0标志可以设置输入记录分隔符,以便为Mac文件使用“\ _”。

$ perl -e "print qq{aa\raa\raa}" > t.txt
$perl -015 -p -i.ori -e 's/a/b/' t.txt
$cat t.txt
ba
$ perl -MO=Deparse -015 -p -i.ori -e 's/a/b/'.txt
BEGIN { $^I = ".ori"; }
BEGIN { $/ = "\r"; $\ = undef; }
LINE: while (defined($_ = <ARGV>)) {
    s/a/b/;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

答案 1 :(得分:0)

来自perlrun documentation

-p assumes an input loop around your script. Lines are printed.
-i files processed by the < > construct are to be edited in place.
-e may be used to enter a single line of script. Multiple -e commands may be given to build up a multiline script.