2010-02-11 81 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