查询的详细信息如下:
\t\n
结尾的行,这是一个微不足道的测试,而不是此问题的主题。这样一来,就可以立即删除大约75%的生产线,从而减轻工作量。2,3,12-18,25-28,31
字段。一种选择是显然使用以下简单的代码,我已经尝试过将其很好地格式化并包括注释以显示我的推理:
use warnings;
use strict;
# I am using the latest stable version of Perl for this exercise
use 5.30.0;
while (<>)
{
# Skip lines ending with an empty field
next if substr($_,-2) eq "\t\n";
# Remove "\n"
chomp;
# Split matching lines into fields on "\t", creating @fields
my @fields=split(/\t/,$_);
# Copy only the desired fields from @fields to create a new
# line in TSV format
# This can be done in one simple step in Perl, using
# array slices and the join() function
my $new_line=join("\t",@fields[2,3,12..18,25..28,31]);
# ...
}
但是,使用split
会导致额外的解析(超出了我需要的最后一个字段),并生成了我也不需要的完整字段数组。我认为不创建数组,而是解析每行以寻找制表符并在我进行操作时对字段索引进行计数,在创建途中创建输出行,并在我需要的最后一个字段处停止,会更有效率。
我是在评估中纠正还是只是做一个简单的split
,然后是包含感兴趣字段的join
切片,那么从性能角度来看,这是最好的方法吗?
更新:不幸的是,没有人提到使用GNU cut
进行拆分并将结果通过管道传输到Perl进行其余处理的可能性。这可能是最高效的方式,无需编写大量的自定义(C)代码来执行此操作,也无需借助自定义行解析(也使用C)来进行基于大型块的读取。
答案 0 :(得分:5)
您可以使用其limit参数告诉split何时停止:
std::forward<O>(o).value()
(指定一个多于您实际想要的字段数,因为它产生的最后一个字段将包含该行的其余部分。)
答案 1 :(得分:0)
grep -P -v "\t\s*$" yourFile.tsv | cut -f2,3,12-18,25-28,31
您甚至不必为此编写Perl代码。
在这里
-P
是“ perl grep”,它为朴素的grep提供了更多功能。
-v
是逆向匹配,与您的next if
顺便说一句,如果您有足够的核心和内存,那么您可能希望通过拆分和合并为以下内容来加快处理速度:
split -n 10 -d yourFile.tsv yourFile.tsv.
这将生成yourFile.tsv.00, ..., yourFile.tsv.09
因此,整个代码类似于下面的代码块:
`split -n 10 -d yourFile.tsv yourFile.tsv.`
@yourFiles = `ls yourFile.tsv.*`;
foreach $file (@yourFiles) {
`grep -P -v "\t\s*$" $file | cut -f2,3,12-18,25-28,31 > $file.filtered &`;
}
`cat yourFile.*.filtered > final.output.tsv`