Левое внешнее соединение на двух файлах в unix
Мне нужно объединить два файла в два поля. Однако я должен получить все значения в файле 1, даже если соединение завершится неудачно, как левое внешнее соединение.
Файл 1:
01|a|jack|d
02|b|ron|c
03|d|tom|e
Файл 2:
01|a|nemesis|f
02|b|brave|d
04|d|gorr|h
выход:
01|a|jack|d|nemesis|f
02|b|ron|c|brave|d
03|d|tom|e||
Ответы
Ответ 1
Это join -t '|' file1 file2 -a1
Используемые опции:
t: разделитель.
a: определяет номер файла, из которого должны быть напечатаны неспаренные строки.
join -t '|' file1 file2 -a2
выполнит правое внешнее соединение.
Пример прогона
[[email protected] test]$ cat f1
01|a|jack|d
02|b|ron|c
03|d|tom|e
[[email protected] test]$ cat f2
01|a|nemesis|f
02|b|brave|d
04|d|gorr|h
[[email protected] test]$ join -t '|' f1 f2 -a1
01|a|jack|d|a|nemesis|f
02|b|ron|c|b|brave|d
03|d|tom|e
Ответ 2
Чтобы сделать то, что задает вопрос, немного сложнее, чем предыдущий ответ, и потребовалось бы что-то вроде этого:
sed 's/|/:/2' file1 | sort -t: >file1.tmp
sed 's/|/:/2' file2 | sort -t: >file2.tmp
join -t':' file1.tmp file2.tmp -a1 -e'|' -o'0,1.2,2.2' | tr ':' '|'
Unix join может присоединяться только к одному полю AFAIK, поэтому вы должны использовать файлы, которые используют другой разделитель, для "объединения двух файлов в два поля", в этом случае первые два поля. Я буду использовать двоеточие :, но если : существует в любом из входных данных, вам нужно будет использовать что-то другое, например, символ табуляции может быть лучшим выбором для производство использование. Я также повторно сортирую вывод в новом составном поле sort -t:
, который для примера входных файлов не имеет никакого значения, но для реальных данных. sed 's/|/:/2'
заменяет второе вхождение канала на двоеточие в каждой строке файла.
file1.tmp
01|a:jack|d
02|b:ron|c
03|d:tom|e
file2.tmp
01|a:nemesis|f
02|b:brave|d
04|d:gorr|h
Теперь мы используем вывод join
, отфильтрованный tr
, с несколькими дополнительными опциями:
-
-t':'
укажите промежуточный разделитель двоеточия
-
-a1
левое внешнее соединение
-
-e'|'
указывает строку замены для неудачных объединений, в основном конечный разделитель вывода N-1 раз, где N - это число полей с разделителями каналов, соединенных справа от двоеточия в файле2.tmp. В этом случае N = 2, поэтому один символ трубы.
-
-o'0,1.2,2.2'
указывает формат вывода:
-
0
поле объединения
-
1.2
поле 2 файла1.tmp, то есть все права двоеточия
-
2.2
поле 2 файла2.tmp
-
tr ':' '|'
Наконец, мы переводим двоеточия обратно в каналы для окончательного вывода.
Выход теперь соответствует выходному образцу вопроса, который не был выполнен предыдущим ответом:
01|a|jack|d|nemesis|f
02|b|ron|c|brave|d
03|d|tom|e||
Ответ 3
У меня недавно была эта проблема с очень простым входным файлом, всего одним полем, поэтому без разделителей.
cat file1 > k1
cat file2 >> k1
sort k1 | uniq -c | grep "^.*1 "
will give you lines that occur in only 1 file
Это особый случай, он может быть неприменим или не сравним с вышеприведенными методиками, опубликованными здесь, но его можно использовать в случае, если он полезен для кого-то, кто ищет левые внешние соединения (то есть только для непревзойденных случаев). Грэп для "^. * 2" даст вам подходящие случаи. Если у вас есть файл с несколькими полями (более распространенный случай), но вы заботитесь только об одном поле соединения, вы можете использовать Awk для создания файла только для ключа (для каждого файла), а затем обработать, как описано выше.