您好,有一个表格文件(分隔符= \t
)A.txt
:
205 toto patho
207 tata benign
208 titi likely_patho
和B.txt
:
210 lolo patho
211 lala benign
212 lili benign
我想要一个文件,如果第三列是“patho”或“likely_patho”,则打印第二列的值。通过这个例子,我们有:
A toto;titi
B lolo
为了做到这一点,我做了:
for bla in *.txt; do
r="$(basename -s ".txt" $bla)"
awk -v filename=$r '($3=="patho" || $3=="likely_patho") {print filename"\t"$2}' $bla >> result.txt ;
done
但是,如果文件包含多个匹配项(例如A.txt
),则此代码为每个匹配项提供一行:
A toto
A titi
B lolo
我怎样才能有正确的输出?谢谢
答案1
使用任何 awk:
$ cat tst.awk
BEGIN {
split(t,tmp)
for ( i in tmp ) {
tgts[tmp[i]]
}
FS = OFS = "\t"
}
FNR == 1 {
fname = FILENAME
sub(/\.[^.]*$/,"",fname)
}
$3 in tgts {
hits[fname] = (fname in hits ? hits[fname] ";" : "") $2
}
END {
for ( fname in hits ) {
print fname, hits[fname]
}
}
$ awk -v t='patho likely_patho' -f tst.awk *.txt
A toto;titi
B lolo
答案2
尝试 :
awk ' FNR==1 { f=FILENAME;
sub(/\.[^.]*$/,"",f);
printf "%s%s\t",aline,f;
aline="\n";
s=""
}
($3=="patho" || $3=="likely_patho"){
printf "%s%s",s,$2;
s="; "
}
END{print ""}
' ./*.txt
答案3
尝试一下(可以是一行)
awk -v filename="$r" 'BEGIN { string=filename "\t" }
($3=="patho" || $3=="likely_patho") {printf string $2; string=";" }
END { printf "\n" } ' $bla >> result.txt ;
我使用string
作为前缀,它将首先打印文件名,然后是分号。
您需要添加最后的换行符。
答案4
使用 perl(带有额外的换行符以提高可读性):
$ perl -MFile::Basename -F'\t' -le '
$f = fileparse($ARGV, qw(.txt)) if $. == 1;
if ($F[2] =~ /^(likely_)?patho$/) {
push @{ $files{$f} }, $F[1]
};
close(ARGV) if eof; # close each input file and reset the line counter $. at eof
END {
foreach (sort keys %files) {
print "$_\t", join(";",@{ $files{$_} })
}
}' A.txt B.txt
A toto;titi
B lolo
-MFile::Basename
告诉 perl 加载文件::基本名称模块。这是一个核心 Perl 模块,包含在 Perl 中。-F
设置字段分隔符(制表符),还启用 Perl 的-a
自动拆分模式(将每个输入行拆分为名为 的数组@F
,类似于 awk),以及 Perl 的-n
迭代其输入的选项(行为类似于sed -n
和awk
)。-l
启用自动处理行结束符(\n
默认情况下)。简而言之,它从每个输入行的末尾删除换行符(使用 perl 的chomp()
函数)并将它们添加到每个语句的末尾print
。所有 perl 命令行选项都记录在
man perlrun
.
该脚本迭代每个输入行,每当它在第三个字段($F[2]
-perl 数组索引从零开始)中找到匹配项时,它就会将第二个字段添加到名为 的数组哈希 (HoA) 中%files
。这是一个哈希(关联数组),其中键是基本文件名,值是第二字段字符串的数组。有关 perl 数据结构的更多信息,请参阅perldata
、perllol
和的手册页。perldsc
当所有输入被读取和处理后,它以请求的格式输出数据,并按文件名排序。
注意:... if $. == 1;
与该close(ARGV) if eof
行一起确保仅在每个新文件的第一行提取基本文件名。这不是必需的,只是一个小的优化,只有当您有非常大的输入文件时才会有用。如果您喜欢稍微短一点的一行或者如果性能不是问题,请删除该close(ARGV) ...
行和if $. == 1
条件。