【问题标题】:Programmatically read from STDIN or input file in Perl在 Perl 中以编程方式从 STDIN 或输入​​文件中读取
【发布时间】:2011-03-09 11:51:58
【问题描述】:

在 Perl 中以编程方式从标准输入或输入文件(如果提供)读取的最巧妙方法是什么?

【问题讨论】:

    标签: perl stdin


    【解决方案1】:
    while (<>) {
    print;
    }
    

    将从命令行指定的文件中读取,如果没有给出文件,则从标准输入中读取

    如果您需要在命令行中进行此循环构造,则可以使用-n 选项:

    $ perl -ne 'print;'
    

    在这里,您只需将第一个示例中的{} 之间的代码放入第二个示例中的''

    【讨论】:

    • +1 +nitpick: "将从命令行连续指定的一个或多个文件中读取"
    • ...您需要做的就是编写@ARGV = "/path/to/some/file.ext"; 并读取文件——因此您甚至可以在特定条件下编写默认文件。
    • 如果你的脚本很短,你可以使用 perl 的 -n 或 -p 选项,并在命令行中指定你的处理:perl -n -e '$_ = uc($_); print;' yourfile。使用 -p 而不是 -n,perl 会自动在末尾打印 $_。
    • 当然你可以一口气“啜饮”所有东​​西:my @slurp = &lt;&gt;; foreach my $line (@slurp) { ... }
    • 是否有理由不使用 while (my $line = &lt;&gt;) {... 之类的名称命名读取行?
    【解决方案2】:

    这提供了一个可以使用的命名变量:

    foreach my $line ( <STDIN> ) {
        chomp( $line );
        print "$line\n";
    }
    

    要读取文件,请像这样通过管道输入:

    program.pl < inputfile
    

    【讨论】:

    • +1 用于避免所有太常见的速记不可读的 Perl 代码
    • -1 因为 foreach 会吞下整个文件。最好在 while 循环中分配给该行。此外,Perl 为裸尖括号内置了神奇的行为,所以你应该说 while(my $line = )。那么就不需要重定向了。
    • 第一行应该是foreach my $line ( &lt;STDIN&gt; ) { 我同意@MikeKulls。如果 Perl 脚本不可读,这不是 Perl 的错。程序员是罪魁祸首!
    • 重读问题这个响应是不正确的,因为它只从标准输入读取,不读取命令行上指定的文件。 ennukiller 的回答是正确的,虽然我会把它写成while(my $line = &lt;&gt;) { print $line; }
    • @MikeKulls 不应该是while (my $line = &lt;&gt;, defined $line) { ... }while (&lt;&gt;) { my $line = $_; } 以避免停在空行上吗?
    【解决方案3】:

    在某些情况下,“最巧妙”的方法是利用-n switch。它使用while(&lt;&gt;) 循环隐式包装您的代码并灵活处理输入。

    slickestWay.pl:

    #!/usr/bin/perl -n 开始: { # 在这里做一次 } # 实现单行输入的逻辑 打印$结果;

    在命令行:

    chmod +x slickestWay.pl
    

    现在,根据您的输入执行以下操作之一:

    1. 等待用户输入

      ./slickestWay.pl
      
    2. 从参数中指定的文件读取(不需要重定向)

      ./slickestWay.pl input.txt
      ./slickestWay.pl input.txt moreInput.txt
      
    3. 使用管道

      someOtherScript | ./slickestWay.pl 
      

    BEGIN 块是必要的,如果您需要初始化某种面向对象的接口,例如 Text::CSV 或类似的,您可以使用 -M 添加到 shebang。

    -l-p 也是你的朋友。

    【讨论】:

      【解决方案4】:

      你需要使用操作符:

      while (<>) {
          print $_; # or simply "print;"
      }
      

      可以压缩成:

      print while (<>);
      

      任意文件:

      open F, "<file.txt" or die $!;
      while (<F>) {
          print $_;
      }
      close F;
      

      【讨论】:

        【解决方案5】:

        如果你有一个原因不能使用上面 ennukiller 提供的简单解决方案,那么你将不得不使用 Typeglobs 来操作文件句柄。这是更多的工作。此示例从$ARGV[0] 中的文件复制到$ARGV[1] 中的文件。如果未指定文件,则分别默认为STDINSTDOUT

        use English;
        
        my $in;
        my $out;
        
        if ($#ARGV >= 0){
            unless (open($in,  "<", $ARGV[0])){
              die "could not open $ARGV[0] for reading.";
            }
        }
        else {
            $in  = *STDIN;
        }
        
        if ($#ARGV >= 1){
            unless (open($out, ">", $ARGV[1])){
              die "could not open $ARGV[1] for writing.";
            }
        }
        else {
            $out  = *STDOUT;
        }
        
        while ($_ = <$in>){
            $out->print($_);
        }
        

        【讨论】:

        • +1 如果要从 读取的文件名不是 在命令行上提供但在其他地方(在某些变量中,从配置文件等读取 - 你只是用其他变量替换 $ARGV[0] 等)所有其他答案都失败了......
        • 或者,对于阅读,只需将文件名unshift 转换为@ARGV 并使用菱形运算符&lt;&gt;
        【解决方案6】:

        $userinput =  <STDIN>; #read stdin and put it in $userinput
        chomp ($userinput);    #cut the return / line feed character
        

        如果你只想读一行

        【讨论】:

        • 只从 STDIN 中读取,而不是从指定文件中读取。钻石运算符正是 OP 正在寻找的。​​span>
        【解决方案7】:

        以下是我如何制作一个可以接受命令行输入或重定向文本文件的脚本。

        if ($#ARGV < 1) {
            @ARGV = ();
            @ARGV = <>;
            chomp(@ARGV);
        }
        


        这会将文件的内容重新分配给@ARGV,从那里您只需处理@ARGV,就好像有人包含命令行选项一样。

        警告

        如果没有文件被重定向,程序将处于空闲状态,因为它正在等待来自 STDIN 的输入。

        我还没有想出一种方法来检测文件是否被重定向以消除 STDIN 问题。

        【讨论】:

        • 这是一个很酷的方法,但不是 OP 所要求的。这使得可以将单个文件名作为参数传递,其内容用作命令行参数。 OP 正在寻找不同的东西。另外,为什么神秘的$#ARGV &lt; 1 而不是(我认为的)更清晰的@ARGV == 1
        【解决方案8】:
        if(my $file = shift) { # if file is specified, read from that
          open(my $fh, '<', $file) or die($!);
          while(my $line = <$fh>) {
            print $line;
          }
        }
        else { # otherwise, read from STDIN
          print while(<>);
        }
        

        【讨论】:

        • 普通的&lt;&gt; 操作符会自动查找和读取命令行中给出的任何文件。不需要if
        • 你也没有描述shift在这里做什么
        猜你喜欢
        • 2010-12-17
        • 1970-01-01
        • 2012-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-18
        相关资源
        最近更新 更多