我想要一个 Perl 单行代码来检查输入文件的第一个字段是否是文件名,如果不是,则将文件名添加为每行的第一列。
shell 中编写的示例:
for f in *file*.csv;
do
file_column=`cat ${f} | awk -F',' '{print$1}'`
if [ $file_column != ${f} ]
then
sed -i "s/^/$f,/" $f 2>/dev/null;
fi
done
但上述方法检查文件名是否存在于第一列中,如果不存在则添加它,对于 4 Laks 文件大约需要 3 小时。我知道 Perl 对于文件操作更快。
我尝试过的 Perl 命令:
perl -p -i -e 's/^/Welcome to Hell,/' file*.csv
请帮助我添加逻辑来检查该字段是否已存在,并且仅在不存在时才进行更改。
Input : file1.csv
col1,col2,col3
data1,data2,dat3
Output: file1.csv
file1.csv,col1,col2,col3
file1.csv,data1,data2,data3
或者如果这里有任何更快的方法请建议。 Perl 一个衬垫,因为它是另一个 shell 脚本的一部分,所以我想小调用会更好(请建议)
答案1
这是你的 perl 一行:它适用于多个文件参数
perl -i -pe '/^$ARGV,/ or print "$ARGV,"' file1 file2 ...
$ARGV
是保存当前文件文件名的魔法变量。
请参阅http://perldoc.perl.org/perlvar.html#Variables-lated-to-filehandles
字段分隔符(逗号)是硬编码的。您可以决定这是否有问题。
小的性能改进:
perl -i -pe 'index($_, "$ARGV,") == 0 or print "$ARGV,"' file1 file2 ...
答案2
在讲述 perl 速度之前尝试加速你自己的脚本
for f in *file*.csv;
do
sed -i "/^$f,/! s/^/$f,/" "$f"
done
答案3
虽然您实际上可以使用 Perl 做到这一点,但语法并不是最简单的(或者至少,它不是我能想到的最好的)。使用其他工具可能会更简单、更快。例如,
gawk(相对较新的版本)
for f in file*csv; do awk -i inplace -F, '{ if($1==FILENAME){print} else{print FILENAME","$0} }' "$f"; done
答案4
无法管理单行,但这里有一个珀尔脚本。将其放入文件中并使其可执行。然后将*.csv
文件名作为参数指定给它。它创建*.new
文件。如果您确信它有效,请取消注释
rename
最后的命令。
#!/usr/bin/perl
use strict;
foreach my $file(@ARGV){
open(F,$file) or die "$file:$!";
$_ = <F>;
next if $_=~/^$file,/;
open(OUT,">$file.new") or die;
my $add = "$file,";
print OUT $add,$_;
while(<F>){
print OUT $add,$_;
}
close OUT;
close F;
#rename("$file.new","$file");
}