根据第一列将多个 Unix 文件拆分为多个文件

根据第一列将多个 Unix 文件拆分为多个文件

我有几个文件 (*data.txt),我试图根据第 1 列的内容将每个文件拆分为多个文件。我已设法将它们拆分,但我不知道如何使用 和 命名输出$filename文件第 1 列($1) 使用print.目前,以下命令中的打印给了我$1 ".txt",例如:ENSG00000108094.txt,ENSG00000115232.txt而不是file1_ENSG00000108094.txt,file1_ENSG00000115232.txt,这是不合适的,因为我需要为每个输入文件提供单独的输出。这是我的命令,我不确定应该在哪里使用"$b"才能获得预期的结果。

for filename in *_data.txt
 do
    b=${filename%%_data.txt}
cat $filename | awk 'NR==1 {header = $0; next}!header_printed[$1]++ {print header > $1".txt"}{print > $1".txt"}'
done

谢谢。

答案1

有多种方法可以将 shell 变量传递到 awk 程序中:

  1. 使用-v命令行选项:

    awk -v b=${filename%data.txt} '... {print > (b $1 ".txt")}'
    
  2. 在 awk 程序之后将值作为普通参数传递

    awk '... {print > (b $1 ".txt")}' b=${filename%data.txt}
    
  3. 传递值在环境并通过内部ENVIRON数组在 awk 中访问它

    b=${filename%data.txt} awk '... {print > (ENVIRON["b"] $1 ".txt")}'
    

但是,如果您只有“几个”文件,则完全省略 shell 循环并将所有通配文件直接传递给 awk 可能是有意义的,您可以在其中从FILENAME内部变量导出输出文件前缀,例如:

awk '
  FNR==1 {header = $0; b = FILENAME; sub(/data.txt$/,"",b); next}
  !header_printed[b $1]++ {print header > (b $1 ".txt")}
  {print > (b $1 ".txt")}
' *_data.txt

(您也可以使用splitorsubstr删除data.txt后缀 - 我使用正则表达式,sub因为它最接近${filename%data.txt}shell 扩展)。

相关内容