2010-06-29 90 views

回答

72
while (<>) { 
print; 
} 

将读取从在t上指定的文件他命令行或标准输入,如果如果你需要在命令行这个循环结构没有给出文件

,那么你可以使用-n选项:

$ perl -ne 'print;' 

在这里,你只要把从第一个例子{}之间的代码进入第二

+21

+1 + nitpick:“将从命令行上连续指定的一个或多个文件中读取” – msw 2010-06-29 07:57:31

+4

...并且您需要做的就是编写“@ARGV =”/path/to/some/file.ext “;它读取文件 - 所以你甚至可以在某些条件下编程一个默认文件。 – Axeman 2010-06-29 13:54:05

+2

如果脚本非常短,可以使用-n或-p选项来perl,并在命令行上指定处理: 'perl -n -e'$ _ = uc($ _);打印;' yourfile'。用-p代替-n,perl自动在最后打印$ _。 – mivk 2012-01-09 10:46:19

12

您需要使用<>运营商:

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

这可以压缩到:

print while (<>); 

任意文件:

open F, "<file.txt" or die $!; 
while (<F>) { 
    print $_; 
} 
close F; 
-2
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(<>); 
} 
+7

普通的'<>'操作符会自动从命令行中给出的任何文件中查找和读取。没有必要使用'if'。 – 2010-06-29 08:27:16

+0

你也没有描述'shift'在这里做什么 – 2017-07-08 13:14:32

6

''

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

,如果你想读的只有一行

+0

只从STDIN读取,而不是从指定的文件读取。钻石操作员*完全* OP所要查找的内容。 – 2018-01-20 23:14:36

34

这提供了一个名为变量一起工作:

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

要读取一个文件,管道就在这样的:

program.pl < inputfile 
+7

+1,用于避免所有太常见的速记不可读的Perl代码 – MikeKulls 2013-12-11 23:55:00

+3

-1因为foreach会啜泣整个文件。最好在while循环中分配给该行。此外,Perl内置了尖角括号的神奇行为,所以你应该说while(my $ line = <>)。那么不需要重定向。 – 2014-07-07 16:12:27

+2

第一行应为'foreach my $ line(){' 我同意@MikeKulls。如果Perl脚本不可读,这不是Perl的错。程序员应该责怪这里! – tiktak 2014-12-13 13:01:12

10

的在某些情况下,“最清晰”的方式是利用-n switch。它隐式地用while(<>)循环包装您的代码并灵活地处理输入。

slickestWay.pl

 
#!/usr/bin/perl -n 

BEGIN: { 
    # do something once here 
} 

# implement logic for a single line of input 
print $result; 

在命令行:

chmod +x slickestWay.pl 

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

  1. 等待用户输入

    ./slickestWay.pl 
    
  2. 从参数命名的文件(S)阅读(无需重定向)

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

    someOtherScript | ./slickestWay.pl 
    

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

-l and -p也是你的朋友。

5

如果你有一个原因不能使用上面提供的ennuikiller提供的简单解决方案,那么你将不得不使用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($_); 
} 
+0

对于一种可以工作的方式,如果从*中读取的文件名不是在命令行中提供的,而是在其他地方提供的(在某些变量中,从配置文件等中读取 - 只需用其他变量替换“$ ARGV [0] )其中所有其他答案都失败...... – 2016-10-30 16:29:46

+0

或者,对于阅读,只需'将'文件名'转移'到'@ ARGV'并使用菱形运算符'<>'。 – 2018-01-20 23:04:53

0

这里是我做了一个脚本,可以采取以下命令行输入或具有重定向的文本文件。就好像有人,包括命令行选项

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


这将重新分配给@ARGV文件的内容,从那里你只是过程@ARGV。

警告

如果没有文件重定向,因为它是从标准输入等待输入程序将坐在自己的闲置。

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

+0

这是一个很酷的方法,但不是OP要求的。这使得传递单个文件名作为参数成为可能,其中的内容被用作命令行参数。 OP正在寻找不同的东西。此外,为什么隐藏的'$#ARGV <1'而不是(我认为)更清晰的'@ARGV == 1'? – 2018-01-20 23:12:58