【问题标题】:Perl module File:Slurp with STDIN pipedPerl 模块文件:带有 STDIN 管道的 Slurp
【发布时间】:2017-09-12 01:59:44
【问题描述】:

我刚刚尝试使用以下 Perl 脚本使用 File::Slurp 模块进行一些文本替换。它适用于在命令行 (BASH) 中作为参数给出的单个文件。

#!/opt/local/bin/perl -w

use File::Slurp qw( edit_file_lines );

foreach my $argnum (0 .. $#ARGV) {
  edit_file_lines { 
    s/foo/bar/g; 
    print $_
  } 
  $ARGV[$argnum];
}

我想修改它以处理管道(即 STDIN),以便它可以处于一系列管道操作的中间: 例如:

command blah|....|my-perl-script|sort|uniq|wc....

更改 Perl 脚本以允许这样做的最佳方法是什么,同时保留现有的在命令行上处理单个文件的能力?

【问题讨论】:

  • 是的,但我没有找到任何解决我的具体问题的方法。使用 File::Slurp 模块的限制排除了 stackoverflow.com/questions/3138649/… 等答案
  • edit_file_lines is ... equivalent of the -pi command line options of Perl。您是否不了解 -pi 的作用,或者您是否有其他原因必须使用 File::Slurp 来完成此任务?
  • 我已编辑您的问题,为您的代码添加缩进。不客气,但下次请自己做。如果您要求一大群人阅读和理解您的代码,那么让代码尽可能易于理解当然是礼貌的做法。
  • 我建议不要使用 File::Slurp。它有很大的问题,而且看起来它们不会很快被修复(例如rt.cpan.org/Public/Bug/Display.html?id=83126 - 编码完全被破坏了)。
  • @mob,是的,我一直在使用命令行 perl -pi,但随着复杂性的增加,我想学习如何在适当的 perl 脚本中进行操作。我举的例子只是最低限度的。

标签: bash perl stdin


【解决方案1】:

要让您的脚本在管道中运行,您可以检查 STDIN 是否连接到 tty

use strict;
use warnings;
use File::Slurp qw( edit_file_lines );

sub my_edit_func {  s/foo/bar/g;  print $_ }

if ( !(-t STDIN) ) {
    while(<>) { my_edit_func }
}
else {
    foreach my $argnum (0 .. $#ARGV) {
        edit_file_lines { my_edit_func } $ARGV[$argnum];
    }
}

有关-t 文件测试运算符的更多信息,请参阅perldoc -X

【讨论】:

  • 这回答了这个问题,因为它允许我使用 File::Slurp 包(或者,一般来说,其他包)。
【解决方案2】:

您只需要以下内容:

local $^I = '';

while (<>) {
  s/foo/bar/g; 
  print;
}

这与perl -i -pe's/foo/bar/'基本相同,只是在使用STDIN时不发出警告。

【讨论】:

  • 我知道这个结构,我的问题需要使用 File::Slurp 包。但@melpomene 的评论让我觉得我可能需要避开那个包裹。
猜你喜欢
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 2012-07-28
相关资源
最近更新 更多