我举例说明我需要做什么:
输入:
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/