2016-06-12 229 views
1

我接到電話numbers.txt文件,該文件是基本符合5號: 他們看起來是這樣的:問題與嵌套循環

1 2 3 4 5 

我試圖做到的,是我想讀從這些號碼行(已經工作),然後在每次迭代中我想添加+1到每一個這是從文件中讀取並打印在屏幕上與打印張數,所以最終的結果應該是這樣的:

1 2 3 4 5 
2 3 4 5 6 
3 4 5 6 7 
4 5 6 7 8 
5 6 7 8 9 

#!/usr/bin/perl 

use strict; 
use warnings; 

open("handle", 'numbers.txt') or die('unable to open numbers file\n'); 
$/ = ' '; 

OUT: for my $line (<handle>) { 
     for (my $a = 0; $a < 5; $a++) { 
      chomp $line; 
      $line += 1; 
      print "$line "; 
       next OUT; 
     } 
} 
close("handle"); 

現在還沒有在perl中完成循環,如果有人能夠提供工作示例,那將是非常好的。

而且,這將是巨大的,如果你能提供一個以上的工作例子,只是要面向未來;) 感謝

+0

請參閱['當某人回答我的問題時該怎麼辦?](http://stackoverflow.com/help/someone-answers)標記答案(如您所見它適合)對於本網站如何運作非常重要,對於稍後搜索的用戶而言非常重要。 – zdim

回答

1

你可以試試這個關於大小。

#!/usr/bin/perl 

use strict; 
use warnings; 

open("handle", 'numbers.txt') or die('unable to open numbers file\n'); 

for my $line (<handle>) { 
    chomp $line; 
    for my $number (split /\s+/, $line) { 
     for (my $a = $number; $a < $number+5; $a++) { 
      print "$a "; 
     }  
     print "\n"; 
    } 
} 
close("handle"); 

你可以用$/=」'分配,而是讓該文件的行外循環迭代。
對於每一行你想迭代每個數字是由空格分隔,因此拆分/ \ S + /,$行它給你一個內部循環的數字列表。 對於您的輸出$ a,從文件讀取的編號開始。

+0

'split/\ s + /'應該幾乎總是被'split'' – Borodin

1

這將做你以後:

use strict; 
use warnings; 

while(<DATA>) { 
    chomp; 
    print "$_\n"; 
    my @split = split; 
    my $count = 0; 
    for (1..4){ 
     $count++; 
     foreach (@split){ 
      my $num = $_ + $count; 
      print "$num "; 
     } 
     print "\n"; 
    } 

} 

__DATA__ 
1 2 3 4 5 
1

更新  添加另一種方法,這一次與發佈方式一致。


遞增字符串中的每個數字,改變字符串到位。重複這一點。以下是兩種方式來做到這一點。另一種方法是按照整數序列讀取單個數字和打印。

(1)用正則表達式。這也符合在單行

echo "1 2 3 4 5" | perl -e '$v = <>; for (1..5) { print $v; $v =~ s/(\d+)/$1+1/eg; }' 

這將打印所需的輸出。但更好地把它放在腳本中

use warnings; 
use strict; 

my $file = 'numbers.txt'; 
open my $fh, '<', $file or die "can't open $file: $!"; 

while (my $line = <$fh>) { 
    # Add chomp($line) if needed for some other processing. 
    for (1..5) { 
     print $line; 
     $line =~ s/(\d+)/$1+1/eg; 
    } 
} 

/e修飾符對此非常重要。它使得正則表達式的替換側被評估爲代碼而不是雙引號字符串。所以你可以在那裏實際執行代碼,在這裏我們添加到捕獲的數字$1+1,對於每個匹配的數字,因爲/g向下移動字符串。這會更改字符串,以便for (1..5)的下一次迭代增加這些等等。我匹配多個數字,\d+,在您的示例中這不是必需的,但通常會更有意義。

(2)經由split + map + join,也重複改變到位線

while (my $line = <$fh>) { 
    for (1..5) { 
     print $line; 
     $line = join ' ', map { $_+1 } split '\s+', $line;    
    } 
} 

split會從$line號碼列表並且將其送至map,其遞增每個,供給它的輸出列表到join。連接的字符串被分配回$line,並重復此操作。我拆分了\s+以允許多個空白區域,但這使得它非常「放寬」它接受的輸入格式,請參閱perlrecharclass。如果您知道這是一個空格,請將其更改爲' '

(3)一次取一個數字並打印從其開始的整數序列。

open my $fh, '<', $file or die "can't open $file: $!"; 
local $/ = ' '; 
while (my $num = <$fh>) { 
    print "$_ " for $num..$num+4; 
    print "\n"; 
} 

神奇4可通過編碼預處理所述整行找到序列長度,通過說

my $len =() = $line =~ /(\d+)/g; 

或通過split -ing到一個數組並考慮其scalar,然後使用$len-1


其他意見。

  • 我建議這三個參數的open,open my $fh, '<', $file

  • 當您檢查調用打印錯誤,die "Your message: $!",看到失敗的原因。如果決定退出,那麼你可能不需要$!。但是當外線呼叫失敗時不知道之所以需要合適的錯誤變量,最常見的是$!

+0

@jonasv更新:增加了另一種方法(更像OP),修正了正則表達式中的blooper,改變了打印效果。 – zdim

1

這裏沒有必要使用嵌套循環它總是程序變慢。

#!/usr/bin/perl 
use strict; 
use warnings; 

my @num = split(" ",(<DATA>)[0]); 

foreach my $inc (0..$#num) 
{ 
    print map{$inc+$_," "}@num; # Add one by one in array element 
    print "\n"; 
} 


__DATA__ 
1 2 3 4 5 
0

您的程序有許多問題。以下是停止工作的原因

  • 您正在將記錄分隔符設置爲單個空格。輸入文件包含"1 2 3 4 5\n",所以while循環將迭代五次設置$line"1 ""2 ""3 ""4 ""5\n"

  • for循環設置爲重複五次。它在chomp $line後刪除號碼後的空格,然後增加$line並打印出來。然後你跳出for循環,執行它只有一次,next OUT。這導致一個遞增和打印的文件中的每個值,讓您得到2 3 4 5 6

  • 刪除不必要的next OUT,產生更接近於現在有被打印在每個號碼

    2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 10 
    

    五個號碼輸入文件

  • for循環幫助後添加print "\n"分開線

    2 3 4 5 6 
    3 4 5 6 7 
    4 5 6 7 8 
    5 6 7 8 9 
    6 7 8 9 10 
    
  • 現在我們需要在之前打印之後,它會遞增,而不是之後。如果我們換$line += 1print "$line "我們得到這個

    1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
    4 5 6 7 8 
    5 
    6 7 8 9 
    

    這到底是怎麼發生的是,5還在其次是換行,現在出現在輸出。 chomp將不會刪除此項,因爲它從字符串的末尾刪除$/的值。您已將其設置爲空格,因此它只會刪除空格。修復方法是用s/\s+//g替換chomp,該替換可從字符串中刪除*全部空格。你也需要做的只有一次,所以我已經把它的for循環外頂部

現在,我們得到這個

1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
    4 5 6 7 8 
    5 6 7 8 9 

這是你的代碼,它結束了

use strict; 
use warnings; 

open("handle", 'numbers.txt') or die('unable to open numbers file\n'); 

$/ = ' '; 

for my $line (<handle>) { 

    $line =~ s/\s+//g; 

    for (my $a = 0; $a < 5; $a++) { 
     print "$line "; 
     $line += 1; 
    } 

    print "\n"; 
} 

close("handle"); 

有可能提高你的程序的其他一些最佳實踐

  • 使用use warnings 'all'

  • 使用詞法文件句柄,並open

  • 三個參數的形式使用local如果要更改Perl的內建變量

  • $!到您die串讓你知道爲什麼open失敗

  • 避免C風格for循環,遍歷一個列表,而不是

使這些修補程序,以及看起來是這樣的。輸出與上面相同

use strict; 
use warnings 'all'; 

open my $fh, '<', 'numbers.txt' 
     or die qq{Unable to open "numbers.txt" for input: $!}; 

local $/ = ' '; 

for my $line (<$fh>) { 

    $line =~ s/\s+//g; 

    for my $a (0 .. 4) { 
     print "$line "; 
     ++$line; 
    } 

    print "\n"; 
}