У меня есть следующий файл:
cat fileA.txt
seattle 1991 west
atlanta 1993 west
turlock 1998 west
marysville 2004 south
newyork 2007 north
canada 2004 west
А второй файл выглядит так:
cat fileB.txt
popular
someWhatPopular
boring
popular
popular
popular
Я хотел бы получить следующий результат fileB.txt
:
popular popular popular someWhatPopular boring popular
По сути, я пытаюсь отсортировать fileB.txt
по fileA.txt
третьему столбцу.
Я попробовал следующий код:
#!/bin/bash
sort -s -k3,3 fileA.txt fileB.txt
Но это не сработало. Есть предложения? Я вполне открыт для всего, что не требует хардкодинга. Bash/awk/sed и т. д.
решение1
Это проблема структуры данных, а не только Linux. Вам нужна общая запись (ключ) в обеих таблицах, чтобы связать их, как и в любой «базе данных», и хорошей практикой является сохранение уникального ключа в первом столбце любой таблицы данных. Затем вы можете сортировать и связывать, как душе угодно.
Взяв что-то вроде @glennjackman mapping, вы определяете ключ сопоставления как север, юг и т. д.
1 south somewhatPopular
2 west popular
3 north boring
4 east unexplored
в файле с именем file popularity
. Изменить, fileA
включив уникальный ключ
1 seattle 1991 west
2 atlanta 1993 west
3 turlock 1998 west
4 marysville 2004 south
5 newyork 2007 north
6 canada 2004 west
затем вы можете манипулировать этими файлами, сопоставляя join
их с выбранным вами ключом (в вашем случае столбец 2 в popularity
сопоставляется со столбцом 4 в fileA
), но join
для этого оба файла должны быть отсортированы по ключевому полю, поэтому
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity) | sort -k2 | awk '{print $6}'
popular
popular
popular
somewhatPopular
boring
popular
Это немного грубый подход, но он обеспечивает максимальную гибкость.
Разбейте указанную выше команду на каждом этапе, и вы увидите, что делает каждый шаг.
Редактировать: Объяснениеjoin -1 4 -2 2 # its in the man pages
Это говорит нам join
о том, что нужно посмотреть на 4-й столбец в таблице 1 (-1 4) и найти соответствующие значения во 2-м столбце таблицы 2 (-2 2).
join
затем объединяет столбцы из двух таблиц в одну таблицу, но включает только ключевой столбец (север и т. д.) один раз. Посмотрите на вывод из
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity)
и это должно быть более ясно
Поскольку нам нужно было отсортировать таблицы данных для join
работы, мы затем
| sort -k2
объединенную таблицу, чтобы вернуть их в исходный порядок.
Нужный вам столбец — это столбец 6 в объединенной таблице, поэтому мы просто
| awk '{print $6}'
на стандартный вывод.
решение2
Вы можете попробовать paste
объединить два файла «таблицы», передать вывод в sort
, а затем cut
оставить только четвертый столбец.
Непроверенная (сейчас это мобильный телефон) попытка будет выглядеть примерно так:
paste fileA fileB | sort -s -k3,3 | cut -f4
решение3
Вы можете получить алфавитное отображение с помощью
paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)
north boring
south popular
west someWhatPopular
И затем желаемый вами вывод можно получить с помощью awk:
awk '
NR==FNR {map[$1] = $2; next}
{print map[$NF]}
' <(paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)) fileA.txt
someWhatPopular
someWhatPopular
someWhatPopular
popular
boring
someWhatPopular