【问题标题】:What does exactly perl -pi -e do?perl -pi -e 到底是做什么的?
【发布时间】:2015-01-25 21:00:47
【问题描述】:

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

在一些 SO 问题上,我可以阅读:

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;
}

【问题讨论】:

    标签: perl


    【解决方案1】:

    您可以通过核心模块 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 文件使用“\r”。

    $ 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
    

    【讨论】:

    • 非常有趣的答案。我仍然有点困惑,因为在此输出中我没有看到任何 openprint $fh $_ 语句。 Perl 如何打开文件? &lt;ARGV&gt; 对我来说类似于 `my @ARGV = qw/foo.txt/;我的 $bar = 我会得到一个错误。我错过了什么对吗?
    • @coin [perlop](http://perldoc.perl.org/perlop.html) 的 I/O Operators 部分有一段以“空文件句柄 很特殊”开头的部分提供了很好的解释。
    • 是的,输出文件的打开和关闭没有显示在 deparse 输出中。它由就地编辑魔法处理。 'perldoc perlrun' 中的 '-i' 部分解释了这一点。 print $_ 可以在 continue 块中看到。不需要 $fh,因为就地编辑魔术选择了默认的输出文件句柄。您可以使用select 命令执行类似的操作。 &lt;ARGV&gt; 据我了解是 &lt;&gt; 的同义词。
    【解决方案2】:

    来自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.
    

    【讨论】:

    • 它没有多大帮助:(
    猜你喜欢
    • 2010-09-28
    • 1970-01-01
    • 2015-08-06
    • 2013-09-02
    • 2014-01-02
    • 2013-10-10
    • 2017-05-08
    • 2022-01-20
    • 2012-10-17
    相关资源
    最近更新 更多