Подтвердить что ты не робот

Левое внешнее соединение на двух файлах в 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||
4b9b3361

Ответ 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 для создания файла только для ключа (для каждого файла), а затем обработать, как описано выше.