如何使用Perl?
为以下输入使用数组索引删除某些单词?file.txt
BOCK:top:blk1
BOCK:block2:blk2
BOCK:test:blk3
加入后:
/BOCK/top/blk1
/BOCK/block2/blk2
/BOCK/test/blk3
预期产出:
/BOCK/blk1
/BOCK/blk2
/BOCK/blk3
我曾尝试过的代码:
use warnings;
use strict;
my @words;
open(my $infile,'<','file.txt') or die $!;
while(<$infile>)
{
push(@words,split /\:/);
}
my $word=join("/",@words);
print $word;
close ($infile);
foreach my $word(@words)
{
if($word=~ /(\w+\/\w+\/\w+)/)
{
print $word;
}
}
答案 0 :(得分:4)
摆脱中间元素的最简单方法是使用splice
。
while ( my $line = <DATA> ) {
my @words;
push( @words, split( /:/, $line ) ); # colon has no special meaning
splice( @words, 1, 1 );
print '/', join( '/', @words );
}
__DATA__
BOCK:top:blk1
BOCK:block2:blk2
BOCK:test:blk3
我认为你想为每一行做到这一点。你所拥有的代码做了别的事情。由于您的@words
声明在while
循环之外,因此每次迭代都会变大,而每个第三个元素都包含换行符\n
,因为您永远不会chomp
。然后,您构建一个长$word
,其中包含所有使用斜杠/
连接的行中的所有单词。然后你尝试匹配三个用斜线连接的单词,这有效。但是您只有一个捕获组,因此永远不会定义$3
。
答案 1 :(得分:2)
代码可以简化和清理,甚至到
my @paths = map { '/' . join '/', (split ':')[0,-1] } <$infile>;
print "$_\n" for @paths;
map在文件句柄读取上强加列表上下文,从而返回文件中所有行的列表。 map
块中的代码应用于每个元素:它split是该行,并获取该列表的第一个和最后一个元素,join是它们,然后预先引导/
。在块内,该行位于variable $_
,split
默认使用。返回结果列表并将其分配给@path
。
已在simbabque's answer中明确说明了已发布代码中的一些错误。
感谢jm666在评论中发现领先/
的要求。
以上也可用于单线
perl -F: -lane'print "/" . join "/", @F[0,-1]' < file.txt > out.txt
-a
启用自动分割模式(使用-n
或-p
),每行都会被分割并在@F
中可用。 -F
开关允许指定要拆分的模式,此处为:
,而不是默认空间。