2015-10-28 3 views
2

Если я хочу использовать join на моей Ubuntu, мне нужно сначала отсортировать оба файла лексически (по join --help), и только затем присоединиться к ним:Bash: соединим числового столбца

tail -n +2 meta/201508_1 | sort -k 1b,1 > meta.txt 
tail -n +2 keywords/copy | sort -k 1b,1 > keywords.txt 
join meta.txt keywords.txt -1 1 -2 1 -t $'\t' 

(я также удалить заголовок из обоих из них с использованием tail)

Но вместо того, чтобы сортировать файлы лексикографически, я бы хотел их отсортировать по цифрам: первый столбец в обоих файлах - это идентификатор.

tail -n +2 meta/201508_1 | sort -k1 -n > meta.txt 
tail -n +2 keywords/copy.txt | sort -k1 -n > keywords.txt 

И затем присоединиться. Но для join эти файлы выглядят несортированный:

join: meta.txt:10: is not sorted: 1023 301000 en 
join: keywords.txt:2: is not sorted: 10 keyword1 

Если добавить к --nocheck-orderjoin, он не присоединяется правильно - она ​​выводит только одну строку.

Как подключить два файла к их числовому идентификатору в bash?

Sample (столбцы разделенные табуляцией):

файл 1

id volume lang 
1 10 en 
2 20 en 
5 30 en 
6 40 en 
10 50 en 

файл 2

id keyword 
4 kw1 
2 kw2 
10 kw3 
1 kw4 
3 kw5 

требуемый выход

1 kw4 10 en 
2 kw2 20 en 
10 kw3 50 en 
+1

Укажите исходные данные ввода и ожидаемый результат. – anubhava

+0

Я добавил два примера ввода и желаемый результат –

+1

Как насчет сортировки входных файлов лексикографически, а затем их присоединения, как в первом примере, но затем вывести ** вывод ** в 'sort -n', чтобы получить числовой порядок ключей? –

ответ

1

Вы можете угробить join в d использование awk вместо:

awk -F'\t' 'FNR==1{next} NR==FNR{a[$1]=$2; next} $1 in a{print $1, a[$1], $2, $3}' file2 file1 | column -t 
1 kw4 10 en 
2 kw2 20 en 
10 kw3 50 en 

Это, вероятно, уже в том порядке, что вы хотите (как в колонке ID в file1). Однако, если вам нужно конкретная сортировка вы можете сделать:

awk -F'\t' 'FNR==1{next} NR==FNR{a[$1]=$2; next} $1 in a{ 
    print $1, a[$1], $2, $3}' file2 file1 | sort -nk1 | column -t 

column -t Обратите внимание, что есть для получения табличного форматированного вывода.

+0

Будет ли он работать для больших файлов? То есть приведет ли он к большому перекрестному продукту и фильтру, или он будет более умным и использовать файлы, сортируемые? –

+0

Нет. Я не имел в виду кеш. Проецирует ли он оба файла одновременно, например 'join', или сначала создает большой кросс-продукт между строками из двух файлов, а затем фильтрует его? –

+1

Нет ни одного кросс-продукта. Сначала он пересекает 'file2' и сохраняет сопоставление' $ 1 -> $ 2' в ассоциативном массиве. Как только он достигнет конца файла2, он переходит через 'file1' и использует хранимые данные ассоциативного массива. Я предлагаю попробовать его на вашем более крупном наборе данных. – anubhava

3

Обе эти работы. Первый из них (sort -b является recommended on the Mac)

join <(sed 1d file1 | sort -b) <(sed 1d file2 | sort -b) | sort -n 

в Linux man page рекомендует sort -k 1b,1

join <(sed 1d file1 | sort -k 1b,1) <(sed 1d file2 | sort -k 1b,1) | sort -n 

В любом случае, вам нужно сортировать их лексически, чтобы присоединиться к ним. В конце вы можете сортировать результат численно.

Смежные вопросы