Shell 提取列';x';从多个文件,并将文件名转换为';x';

Shell 提取列';x';从多个文件,并将文件名转换为';x';,shell,unix,awk,find,cut,Shell,Unix,Awk,Find,Cut,我试图从多个txt文件(file1.txt、file2.txt、、、等)中提取列“m”,并将每列转换为新文件中的一行 下面是file1.txt: contig_1 contig_1 geneX ctg1_886;ctg1_887;ctg1_888 contig_2 contig_2 geneY ctg1_886;ctg1_887;ctg1_888 contig_3 contig_3 genesZ ctg1_886;ctg1_8

我试图从多个txt文件(file1.txt、file2.txt、、、等)中提取列“m”,并将每列转换为新文件中的一行

下面是
file1.txt

contig_1    contig_1    geneX       ctg1_886;ctg1_887;ctg1_888
contig_2    contig_2    geneY       ctg1_886;ctg1_887;ctg1_888
contig_3    contig_3    genesZ      ctg1_886;ctg1_887;ctg1_888
我想要一个
summary.txt
文件,它看起来像:

file1 geneX geneY geneZ
file2 geneA geneY
.
.
.
etc. 

总行号可能因文件而异。我尝试使用
awk
,但没有成功。

根据glenn jackmans的评论建议,GNU awk解决方案如下所示:

awk 'BEGIN {ORS=" "} BEGINFILE{print FILENAME} {print $3} ENDFILE{ printf("\n")}'  file*.txt
awk解决方案可能是这样的(抱歉,只有gnu awk用于测试):

解释

有几种特殊模式:

  • BEGIN
    ,其操作在开始时执行一次。在这里,
    ORS
    (输出记录分隔符)被设置为空格,其效果是从每个原始行获得一个新列,这是转置步骤
  • END
    操作在末尾执行一次
  • BEGINFILE
    ENDFILE
    操作在处理每个文件的开始和结束时执行一次。在这里,
    文件名
    分别打印换行符

假设字段分隔符是多个空间:

for f in file*.txt ; do 
    echo $f `tr -s ' ' < $f | cut -d ' ' -f 3`
done > summary.txt

在awk中,当FNR为1时,使用自定义输出记录分隔符和规则将非常容易。file1.txt是file1.txt的第一行吗?我从这两篇文章中得到了启发不,file1.txt不是file1.txt的第一行。le colname仅在文件名中。请注意,BEGINFILE和ENDFILE需要GNU awk。这确实有效。请您快速注释代码的不同部分。此外,我的文件类似于file1-pattern.txt。上面的代码保留了整个名称,我可以直接在代码中grep部分文件1吗。否则,我可以事后再做。@user3037937我添加了解释。我不知道你需要什么文件名,但是你有完整的awk字符串处理函数,可以从
filename
中提取子字符串,并且只打印与
file1
对应的子字符串@Lars Fisher,非常感谢你的澄清和提取提示。
for f in file*.txt ; do 
    echo $f `tr -s ' ' < $f | cut -d ' ' -f 3`
done > summary.txt
for f in file*.txt ; do 
    echo $f `cut -f 3 $f`
done > summary.txt