Это мой рабочий файл. (Номер столбца и номер строки неизвестны)
key_ID col_1 col_2 col_3
AA 1 1 1
BB 56 2 7
CC 89 5 2
DD 7 77 7
Я хочу отсортировать каждый столбец по двум нижним значениям, чтобы найти их соответствующие key_ID
из первого столбца.
Желаемый результат будет похож на
col_1 col_2 col_3
AA AA AA
DD BB CC
Используя чистый 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
Использовать 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
Подобная идея моему использованию ответа 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
Не a bash
решение, но в SQL это может быть сделано довольно легко:
Во-первых, составьте таблицу:
create table working (key_ID char(2), col_1 integer, col_2 integer, col_3 integer);
insert into working values ("AA", 1,1,1), ("BB", 56, 2,7), ("CC", 89,5,2), ("DD", 7, 77, 7);
Теперь составьте три полученных таблицы с первыми и вторыми значениями, добавьте номер строки к каждому и присоединитесь к ним на номере строки:
set @row_num1 = 0;
set @row_num2 = 0;
set @row_num3 = 0;
select col1.key_ID as col_1, col2.key_ID as col_2, col3.key_ID as col_3 from
(select (@row_num1 := @row_num1 + 1 ) as num,key_ID, col_1 from working order by col_1 limit 2) as col1
join (select (@row_num2 := @row_num2 + 1 ) as num,key_ID, col_2 from working order by col_2 limit 2) as col2 on col1.num = col2.num
join (select (@row_num3 := @row_num3 + 1 ) as num,key_ID, col_3 from working order by col_3 limit 2) as col3 on col1.num = col3.num
дает
+-------+-------+-------+
| col_1 | col_2 | col_3 |
+-------+-------+-------+
| AA | AA | AA |
| DD | BB | CC |
+-------+-------+-------+
хвост-n +2 дает Вам всем кроме направляющейся строки
виды-k2-n вида на 2-м столбце - повторяют это с-k3 и-k4 для других столбцов
главный-n 2 дает Вам лучшие 2 строки
tail -n +2 test | sort -k2 -n | head -n 2
Затем сохраните вывод однако, Вам нужен он.