嵌套循环出现问题



>我得到了一个名为数字的文件.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 filen');
$/ = ' ';
OUT: for my $line (<handle>) {
for (my $a = 0; $a < 5; $a++) {
chomp $line;
$line += 1;
print "$line ";
next OUT;
}
}
close("handle");

已经有一段时间没有在perl中循环了,如果有人可以提供工作示例,那就太好了。

此外,如果您可以提供多个工作示例,那就太好了,只是为了证明未来;) 谢谢

您可以尝试一下尺寸。

#!/usr/bin/perl
use strict;
use warnings;
open("handle", 'numbers.txt') or die('unable to open numbers filen');
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+/$line它为您提供了内部循环的数字列表。 对于输出$a从文件中读取的数字开始。

这将完成您所追求的:

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

这里不需要使用嵌套循环,它总是程序变慢。

#!/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

更新  添加了另一种方法,该方法与发布的方法一致。


递增字符串中的每个数字,就地更改字符串。重复一遍。以下是两种方法。另一种方法是读取单个数字并按照整数序列打印。

(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修饰符对此至关重要。它使正则表达式的替换端被评估为代码,而不是双引号字符串。因此,您实际上可以在那里执行代码,在这里,当/g向下移动字符串时,我们将捕获的数字$1+1添加到每个匹配的数字中。这会更改字符串,以便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;

或者通过将 -ingsplit-ing 到数组中并获取其scalar,然后使用$len-1


其他评论。

  • 我推荐三论点开放,open my $fh, '<', $file

  • 检查呼叫时,请打印错误die "Your message: $!"以查看失败的原因。如果您决定退出,if ($bad) { die "Got $bad" },那么您可能不需要$!。但是当外部调用失败时,您不知道原因,因此您需要合适的错误变量,通常是$!

您的程序存在许多问题。这是阻止它工作的原因

  • 将记录分隔符设置为单个空格。您的输入文件包含"1 2 3 4 5n",因此while循环将迭代五次,$line设置为"1 ""2 ""3 ""4 ""5n"

  • for循环设置为迭代五次。它chomp $line删除数字后面的空格,然后递增$line并打印它。然后你跳出for循环,只执行了一次,next OUT.这会导致文件中的每个值递增 1 并打印,因此您可以获得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不会删除它,因为它会从字符串的末尾删除$/的值。您已将其设置为空格,因此它将仅删除空格。解决方法是将chomp替换为替换s/s+//g,该替换从字符串中删除*所有空格。您也只需要执行此操作一次,因此我将其放在顶部的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 filen');
$/ = ' ';
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的三参数形式

  • 如果要更改 Perl 的内置变量,请使用local

  • $!放入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";
}

最新更新