在Perl中,如何通过菱形操作符对命令行上指定的所有文件进行两次传递?
如果我有一个文本文件,我想运行两种类型的操作,但每个操作必须分别读取文本的每一行。我知道怎么做的唯一方法就是在Perl中,如何通过菱形操作符对命令行上指定的所有文件进行两次传递?,perl,Perl,如果我有一个文本文件,我想运行两种类型的操作,但每个操作必须分别读取文本的每一行。我知道怎么做的唯一方法就是 open out,(">>out.txt"); while (<>){ #operation one } while (<>){ #operation two } close out; openout,(“>>out.txt”); 而(){ #第一次行动 } 而(){ #行动二 } 收尾; 但是,这将仅在第一个while上运行,其中
open out,(">>out.txt");
while (<>){
#operation one
}
while (<>){
#operation two
}
close out;
openout,(“>>out.txt”);
而(){
#第一次行动
}
而(){
#行动二
}
收尾;
但是,这将仅在第一个
while
上运行,其中操作运行正常,但第二个将不会完成,因为第二个while()
实际上不会重新读取文件,而是尝试从第一个while()离开的位置继续。在文件的末尾。那么还有别的办法吗?或者有没有办法告诉第二个while在开始时重新开始?如果没有使用菱形运算符的文件句柄,Perl将检查@ARGV
特殊变量。如果@ARGV
没有元素,则菱形运算符将从STDIN
读取
这是实现您的需求的另一种方式:
my @stdin=<>;
foreach my $item( @stdin ) {
# ...
}
foreach my $item( @stdin ) {
# ...
}
my@stdin=;
foreach my$项目(@stdin){
# ...
}
foreach my$项目(@stdin){
# ...
}
如果您是从实际文件中读取,您可以使用
seek FILEHANDLE,0,0;
但是,您使用的是
stdin
,我认为不可能倒带stdin
并重新开始。如果数据适合内存:
my @lines = <>;
for ( @lines ){
# operation one
}
for ( @lines ){
# operation two
}
my@lines=;
对于(@行){
#第一次行动
}
对于(@行){
#行动二
}
您在评论中提到:
perl example.pl text.txt
答案是-不要使用
,而是打开一个文件句柄
my ( $filename ) = @ARVG;
open ( my $input, "<", $filename ) or die $!;
while ( <$input> ) {
print;
}
seek ( $input, 0, 0 );
while ( <$input> ) {
#something else
}
如果要在命令行上指定多个文件,可以将整个文件包装在foreach
循环中:
foreach my $filename ( @ARVG ) {
## open; while; seek; while etc.
}
如果您需要逐行运行操作,为什么不试试这样的方法呢
sub operation_1 {
my $line = shift;
#processing for operation 1
}
sub operation_2 {
my $line = shift;
#processing for operation 2
}
while(<>) {
my $line = $_;
chomp($line);
operation_1($line);
operation_2($line);
}
子操作\u 1{
我的$line=shift;
#操作1的处理
}
子操作2{
我的$line=shift;
#操作2的处理
}
while(){
我的$line=$\ux;
chomp($line);
行动1($线);
行动2($线);
}
您不能简单地使用以下命令吗
while (<>) {
operation1($_);
operation2($_);
}
当然,如果
读取的不是普通文件或指向普通文件的符号链接,它将失败。(使用seek
的任何解决方案也是如此)唯一可行的方法是将整个文件加载到临时存储器中(例如内存或临时文件)。以下是最简单的例子:
my @lines = <>;
for (@lines) { operation1($_); }
for (@lines) { operation2($_); }
my@lines=;
对于(@lines){operation1($);}
对于(@lines){operation2($);}
您可以在第一次通过前本地化@ARGV
#!/usr/bin/env perl
use strict;
use warnings;
{
local @ARGV = @ARGV;
while (<>){
print "Pass 1: $_";
}
}
while (<>){
print "Pass 2: $_";
}
#/usr/bin/env perl
严格使用;
使用警告;
{
本地@ARGV=@ARGV;
而(){
打印“通过1:$\”;
}
}
而(){
打印“通行证2:$\”;
}
关闭/重新打开文件,或者将其打开。我无法做到这一点,在从命令行perl ex.pl text.txt调用后,我想用一条命令完成所有这一切,就像我说的,倒带文件。这将重置指向所需服务器的文件指针,以便从该点继续读取。e、 g.第一个while将指针保留在文件的末尾,因此您倒带开头,第二个while开始读取,就好像文件刚刚打开一样。@Kostas如果要传递文件名text.txt
将其存储在变量中,请打开指向该文件名的文件句柄,然后从那里而不是从STDIN读取。然后你就可以按照Marc B的建议重新打开文件了;在这两段时间里,它没有改变任何东西,而且@Hunter我不知道如何做你说的我尝试过它,它没有改变任何东西,程序仍然在fist之后结束。@hymie是的,out是结果输出,因为我调用了我在命令行中作为参数读取的文件,使用seek的正确方法是什么?命令是这样的,perl example.pl text.txt难道没有办法吗?@ikegami:如果你想回答这个问题,那就自己回答这个问题。请不要更改我给出的答案中的每一个单词。这个答案充满了失败:(
是
的缩写,不是
,而且肯定不是
(因为stdin
根本不存在)。至于“倒带”ARGV
(或者stdin
),这很容易测试,结果是当它是一个普通文件的句柄时,您就可以了。最初的问题没有提到使用任何参数。他所拥有的只是一个名为
的perl脚本。这将是stdin
,除非专门传递了一个参数,这(再次)他没有说他在做什么。stdin
是公认的“标准输入”的缩写,stdin
是指向stdin
的perl文件句柄。问题的答案是正确的。问题错了不是我的错。以下是OP自己的评论:“因此,当从stdin调用时,我应该将seek与filehandle的默认名称一起使用"。是否确实要本地$/;
?这不会将整个文件拖到一个数组元素中吗?在列表上下文中访问文件句柄将使用$/
记录定界符拖慢它。@Sobrique:Oops。您是对的。修复了它。谢谢。注意:如果
读取某个内容,则查找
解决方案将失败而不是普通文件或普通文件的符号链接。
my @lines = <>;
for (@lines) { operation1($_); }
for (@lines) { operation2($_); }
#!/usr/bin/env perl
use strict;
use warnings;
{
local @ARGV = @ARGV;
while (<>){
print "Pass 1: $_";
}
}
while (<>){
print "Pass 2: $_";
}