bash - 如何根据第一列awk拆分文件

标签 bash unix awk sed

我举例说明我需要做什么:

输入:

name value1 value2 value3
john xxxxx yyyyy qqqqqq
john xxxxx ddddd vvvvvv
john mmmmm jjjjj llllll
paul xxxxx yyyyy qqqqqq
paul ccccc ccccc dddddd

我需要保留标题并根据第一列中的相同名称拆分为文件。 我需要根据第一列继续命名我的输出文件。

输出:

FILE1:john.tsv

name value1 value2 value3
john xxxxx yyyyy qqqqqq
john xxxxx ddddd vvvvvv
john mmmmm jjjjj llllll

FILE2:保罗.tsv

name value1 value2 value3
paul xxxxx yyyyy qqqqqq
paul ccccc ccccc dddddd

INPUT 和 OUTPUT 文件是制表符分开的。 header 始终相同。

我的解决方案非常复杂且缓慢:

head -1 INPUT > header

awk 'NR>1{print $1}' | sort | uniq > names

while read line

 do grep $line INPUT | cat header - > $line.tsv

< names

done

最佳答案

使用 awk 我们可以写类似的东西,

$ awk 'NR == 1{header = $0; next} 
    !($1 in filename){ print header > ($1".tsv") } 
    NR > 1 { print $0 > ($1".tsv"); filename[$1] }' file

它有什么作用?

  • NR == 1{header = $0} 如果读取的记录数是1,这就是header,保存在header 供以后使用。

  • NR > 1 { 打印 $0 > ($1".tsv"); filename[$1] 如果我们已经读取了多条记录,则将行的内容打印到文件名$1,即第一列。

    • filename[$1] 我们将文件名保存在由文件名索引的关联数组中。该数组用于打印出标题。
  • ($1 in filename){ print header > ($1".tsv") } 如果我们在 filename 数组中找不到当前文件名,它是第一次出现。所以我们将标题打印到文件中。


编辑

如果你想对第二列的文件进行排序,那么我们可以先对它们进行排序,然后将它们通过管道传递给 awk,比如,

$ sort -n -k2 file | awk ....
  • -n 数字排序。
  • -k2 按第二个键排序。

如果标题也是数字,这可能不起作用

关于bash - 如何根据第一列awk拆分文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40744116/

相关文章:

Git 命令将我从当前目录移到父目录

performance - 如何在不使用 echo 的情况下 awk 或 grep 变量?

bash - shell - temp IFS 仅作为换行符。为什么这不起作用 : IFS=$(echo -e '\n' )

Bash:尝试在函数输出中附加变量名

bash - grep - 列出不包含两种模式的所有行

linux - 如何实际查找 UNIX 上进程的死锁原因?

unix - 退出后是否可以在屏幕上保持 less 的输出?

c - 替代 lseek 来跟踪文件 (Posix)

bash - 将一个部分复制到一个新文件中

awk 解析字段并包含 1 个管道的文本