У меня есть следующий набор данных в текстовых файлах:
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
Так как Ваши файлы, кажется, содержат отсортированные данные, необходимо смочь использовать эти 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
Вот 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-е поле тока и значения, связанного с ним в хеше.