Как объединить значения от двух различных текстовых файлов?

У меня есть следующий набор данных в текстовых файлах:

file1.txt

a1:b1
a2:b2
a3:b3
a4:b4
a5:b5

file2.txt

b2:c1
b4:c2
b5:c3

Как объединить эти значения для создания выходного файла как это:

output.txt

a2:c1
a4:c2
a5:c3
2
задан 30 July 2015 в 20:37

2 ответа

Так как Ваши файлы, кажется, содержат отсортированные данные, необходимо смочь использовать эти join, команда, например,

join -12 -21 -t: -o1.1,2.2 file1.txt file2.txt > output.txt

Затем

cat output.txt
a2:c1
a4:c2
a5:c3

Видит man join для деталей опций.

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

join -12 -21 -t: -o1.1,2.2 <(sort -t: -k2,2 file1.txt) <(sort -k1,1 file2.txt)
androgynous:hu2nt
gra7vel:fi6nal
cosm4etic:citizen

, результат также будет в отсортированном порядке: если Вы не хотите это, то существует довольно стандартный способ сделать такого рода вещь в awk использование массива, например,

awk -F: 'NR==FNR {a[$2]=$1; next;} ($1 in a) {print a[$1]":"$2;}' file1.txt file2.txt
5
ответ дан 2 December 2019 в 01:28

Вот awk подход:

awk -F: '(NR==FNR){a[$2]=$1; next}($1 in a){print a[$1]":"$2};' file1 file2 > out

Объяснение

  • awk -F: Выполненный awk, установка разделителя полей к :. Это считает каждую входную строку и разделит ее на :. Так, для первой строки file1, 1-е поле ($1) a1 и второе ($2) b1.
  • (NR==FNR){} : Если NR равно FNR. NR текущий входной номер строки и FNR номер строки текущего файла. Эти два будут равны только, в то время как 1-й файл читается.
  • a[$2]=$1; next : сохраните второе поле как ключ в массиве a чье значение является 1-м полем. Затем пропустите к следующей строке.
  • ($1 in a){print a[$1]":"$2} : это выполнится только при чтении второго файла. Если первое поле второго файла является ключевым массивом a, распечатайте значение для того ключа (2-е поле соответствующей строки от file1).

И Perl один:

perl -F: -lanE '$k{$F[0]} ? say "$k{$F[0]}:$F[1]" : ($k{$F[1]}=$F[0]);' file1 file2 > out

Или, если Вы предпочитаете:

perl -F: -lanE '$k{$F[0]} and say "$k{$F[0]}:$F[1]" or ($k{$F[1]}=$F[0]);' file1 file2 

Объяснение

  • perl -F: -lanE : -n означает, "читает каждый входной файл линию за линией и применяют сценарий, данный -E каждому из них". -E, как -e, позволяет Вам передать сценарий командной строке. Различие - это -E активирует некоторые дополнительные опции такой как say. -a включает автоматическое разделение каждой входной строки на символе, данном -F. Вместе, они делают perl действие во многом как awk. Поля разделяются на массив @F и 1-е поле $F[0], 2-е $F[1] и т.д. Наконец, -l новая строка полос (\n) символы от конца каждой строки.
  • $k{$F[0]} ? foo : bar: Если переменная $k{$F[0]} определяется, сделайте нечто, еще запретите.
  • ($k{$F[1]}=$F[0]) : это происходит если $k{$F[0]} не определяется (это - "панель", выше). Это сохранит второе поле как ключ в хеше %k чье значение является 1-м полем.
  • say "$k{$F[0]}:$F[1]" : это будет работать если $k{$F[0]} определяется ("нечто" выше), поэтому если 1-е поле текущей строки было 2-м полем в другой строке. Если это было, печать (say похож print но добавляет новую строку), 1-е поле тока и значения, связанного с ним в хеше.
5
ответ дан 2 December 2019 в 01:28

Другие вопросы по тегам:

Похожие вопросы: