这是我的工作文件。(列号和行号未知)
key_ID col_1 col_2 col_3
AA 1 1 1
BB 56 2 7
CC 89 5 2
DD 7 77 7
我想对每列的底部 2 个值进行排序,以便key_ID
从第一列中找到它们的对应值。
期望输出如下
col_1 col_2 col_3
AA AA AA
DD BB CC
答案1
使用纯bash
:
#!/bin/bash
DATA=/path/to/input_data
COL_NUMS=$(head -1 $DATA | wc -w)
FILES=''
for i in $(seq 2 $COL_NUMS)
do
FILE=$(mktemp)
echo col_$((i-1)) > $FILE
cut -f1,$i -d' ' <(tail -n +2 $DATA | tr -s ' ') |
sort -k2 -g | head -2 | cut -f1 -d' ' >> $FILE
FILES="$FILES $FILE"
done
paste $FILES
rm $FILES
输出:
col_1 col_2 col_3
AA AA AA
DD BB CC
它的作用是逐一单独查看您的列及其标签,例如labels,col1
,然后labels,col2
等等。
for i in $(seq 2 $COL_NUMS)
do
...
cut -f1,$i -d' ' <(tail -n +2 $DATA | tr -s ' ')
然后它对每个组中具有两个最低值的标签进行排序并将它们放入临时文件中。
FILE=$(mktemp)
...
sort -k2 -g | head -2 | cut -f1 -d' ' >> $FILE
在执行此操作时,我们会创建所有这些文件的列表。
FILES="$FILES $FILE"
所以现在我们有一堆包含所需列表的临时文件,我们应该使用paste
命令将它们放在一起并删除这些临时文件:
paste $FILES
rm $FILES
答案2
使用csvsql
自csvkit
:
paste \
<(csvsql -d ' ' -S --query "select key_ID as "col_1" from file order by col_1 limit 2" file) \
<(csvsql -d ' ' -S --query "select key_ID as "col_2" from file order by col_2 limit 2" file) \
<(csvsql -d ' ' -S --query "select key_ID as "col_3" from file order by col_3 limit 2" file)
输出:
col_1 col_2 col_3
AA AA AA
DD BB CC
您应该可以csvkit
通过以下方式安装pip
:
sudo apt install python-pip
sudo pip install csvkit
答案3
与我的答案使用类似的想法csvsql
,但使用paste
和:sort
awk
paste \
<(tail -n+2 file | sort -k2n | awk 'BEGIN{print "col_1"} NR<3{print $1}') \
<(tail -n+2 file | sort -k3n | awk 'BEGIN{print "col_2"} NR<3{print $1}') \
<(tail -n+2 file | sort -k4n | awk 'BEGIN{print "col_3"} NR<3{print $1}')
输出:
col_1 col_2 col_3
AA AA AA
DD BB CC
答案4
tail -n +2 给出除标题行之外的所有内容
sort -k2 -n 对第二列进行排序 - 对其他列重复此操作,并使用 -k3 和 -k4
head -n 2 给出前 2 行
tail -n +2 test | sort -k2 -n | head -n 2
然后根据需要存储输出。