2010-02-11 59 views
2

!C:\ Perl的\ BIN \ perl.exe所在

use strict; 
use warnings; 


my $numArgs = $#ARGV + 1; 
print "thanks, you gave me $numArgs command-line arguments.\n"; 



while (my $line = <DATA>) { 
    foreach my $argnum (0 .. $#ARGV) { 
     if ($line =~ /$ARGV[$argnum]/) 
      { 
       print $line; 
      } 
    } 
} 

__DATA__ 
A 
B 
Hello World :-) 
Hello World ! 

当我通过一个精氨酸,它工作得很好。 比如我经营test.pl一个test.pl乙或** test.pl你好”虽然和foreach混合回路问题

当我走过有两个参数,它的工作原理一段时间只

成功:当我运行test.pl ABtest.pl。你好或** test.pl乙:你好”

失败:当我运行test.pl的Hello World *

制作并输出重复行:

D:\learning\perl>t.pl Hello World 
thanks, you gave me 2 command-line arguments. 
Hello World :-) 
Hello World :-) 
Hello World ! 
Hello World ! 

D:\learning\perl> 

如何解决呢?感谢您的阅读和答复。

[更新] 我不想打印重复的行。

回答

3

我没有看到问题,您的脚本处理__DATA__并测试所有输入的单词:由于“Hello”和“World”每次匹配两次,它会打印4行。

如果您不希望它写多行,只需在print声明后添加last;即可。

+0

Hi Kemp。是的,如你所说。但我不想打印重复的行。谢谢。 – 2010-02-11 08:54:44

+3

然后在'print'语句后面加上'last;'。 – 2010-02-11 08:56:50

+0

它很有效。谢谢! – 2010-02-11 09:00:23

3

你得到重复输出的原因是因为正则表达式$line =~ /Hello/匹配“Hello World”行和$line =~ /World/也匹配两个“Hello World”行。为了防止出现这种情况,您需要添加一些内容来记住__DATA__部分中的哪些行已被打印,以便在与另一个参数匹配时可以跳过打印。

此外,一些很轻微的文体清理:

#!C:\Perl\bin\perl.exe 
use strict; 
use warnings; 

my $numArgs = @ARGV; 
print "thanks, you gave me $numArgs command-line arguments.\n"; 

while (my $line = <DATA>) { 
    foreach my $arg (@ARGV) { 
     if ($line =~ /$arg/) 
      { 
       print $line; 
      } 
    } 
} 

__DATA__ 
A 
B 
Hello World :-) 
Hello World ! 
  • 使用在标量上下文数组形式返回其大小,所以$size = @arr优于$size = $#arr + 1

  • 如果你不打算除了通过数组索引(for $i (0..$#arr) { $elem = $arr[$i]; ... })以外,还可以使用计数器,然后只需循环遍历数组(for $elem (@arr) { ... })就可以更简单,更直接。

foreach循环也可以用一个grep说法代替,但我会离开,作为一个练习留给读者。

+0

+1嗨戴夫,非常感谢您的完美解剖。 – 2010-02-11 09:44:07

+0

嗨戴夫,我发现了一个错误。如果我运行'test.pl World Hello',(swap * Hello World * to * World Hello *)输出仍然错误。 :-) – 2010-02-11 09:51:39

1

假设您希望只在DATA的每一行中打印一行,如果一个或多个模式匹配,则可以使用grep。请注意,使用\Q可在命令行参数中引用正则表达式元字符,并使用@patterns数组来预编译模式。

if grep { $line =~ $_ } @patterns出声:如果$line匹配一个或多个图形 ;-)

#!/usr/bin/perl 

use strict; use warnings; 

printf "Thanks, you gave me %d command line arguments.\n", scalar @ARGV; 

my @patterns = map { qr/\Q$_/ } @ARGV; 

while (my $line = <DATA>) { 
    print $line if grep { $line =~ $_ } @patterns; 
} 

__DATA__ 
A 
B 
Hello World :-) 
Hello World ! 

这里是你的脚本一些意见,以帮助您了解:

my $numArgs = $#ARGV + 1; 
print "thanks, you gave me $numArgs command-line arguments.\n"; 

命令行参数在@ARGV(请阅读文档)。在标量上下文中,@ARGV计算出该数组中元素的数量。因此,你可以简单地使用:

printf "Thanks, you gave me %d command line arguments.\n", scalar @ARGV; 

此外,您可以通过的@ARGVforeach循环,而不是索引访问的元素直接迭代。现在

while (my $line = <DATA>) { 
    foreach my $arg (@ARGV) { 
     if ($line =~ /$arg/) { 
      print $line; 
     } 
    } 
} 

,会发生什么你的计划,如果我通过(给它的命令行?或者,即使World?应该发生什么?

+0

Selam Sinan,Teşekkürederim – 2010-02-12 01:00:13

+0

顺便说一句,当我通过'('到我的程序上面,产生并产生一个错误'不匹配(在正则表达式;标记为< - HERE在m /(< - HERE/at D:\ learning \ perl \ t .pl line 13, line 1.',否则World?很好,你的脚本在上面修正了这个bug。 – 2010-02-12 01:19:38

+0

@Nano HE Rica ederim ;-)主要问题是, World?'匹配输入,因为'__DATA__'中没有字符串'World?',它是匹配的,因为'd?'表示'd'在模式中是可选的,在模式中使用'\ Q'在'qr'中插入'$ _'意味着'?'会被引用,现在'?'必须直接匹配。 – 2010-02-12 01:20:06