Объедините два файла и сохраните несовпадающие строки - PullRequest
0 голосов
/ 19 февраля 2020

Я изучаю команду sed, но у меня проблема при объединении 2 файлов.

file1.txt

A       1
C       3
E       5

file2.txt

1 John Lennon
2 Mariah carey
3 Cool & The Gang
4 Westlife
5 Red Hot Chili Peppers

желательный вывод

1 John Lennon A
2 Mariah Carey
3 Cool & The Gang C
4 Westlife
5 Red Hot Chili Peppers E

Я пытаюсь сделать сценарий awk следующим образом:

awk 'FNR==NR{seen[$1]=$2; next} $1 in seen{seen[$1]=seen[$1] OFS $2} END{ for (e in seen) print e, seen[e]}' file2.txt file1.txt | sort -V

, но этот вывод отображает только одно слово певца (John, Mariah, Cool, Westlife и Red) и не отображает полное имя певца. Что-то не так с моим сценарием?

Ответы [ 3 ]

2 голосов
/ 19 февраля 2020

Это можно сделать с помощью довольно простого двухэтапного процесса в awk, и нет необходимости использовать sort, поскольку мы можем обработать file2 на втором этапе:

awk 'FNR==NR{seen[$2]=$1; next} $1 in seen{$0 = $0 OFS seen[$1]} 1' file1 file2

1 John Lennon A
2 Mariah carey
3 Cool & The Gang C
4 Westlife
5 Red Hot Chili Peppers E
1 голос
/ 19 февраля 2020

Если столбцы двух файлов разделены табуляцией, а не пробелами (похоже, первый - второй, я не знаю; к сожалению, уценка SO не является вкладкой), это тривиальный join:

$ join -12 -21 -o 0,2.2,1.1 -t$'\t' -a2 <(sort -t$'\t' -k2,2 file1.txt) <(sort -t$'\t' -k1,1 file2.txt)
1   John Lennon A
2   Mariah carey    
3   Cool & The Gang C
4   Westlife    
5   Red Hot Chili Peppers   E

(join требует, чтобы его файлы были отсортированы лексикографически по столбцу соединения, а не по номерам, следовательно, sort s).

Если между номером и полосой в файле2 есть только пробел, сначала преобразуйте его во вкладку с помощью sed:

join -12 -21 -o 0,2.2,1.1 -t$'\t' -a2 <(sort -t$'\t' -k2,2 file1.txt) <(sed 's/ /\t/' file2.txt | sort -t$'\t' -k1,1)
1 голос
/ 19 февраля 2020

Вы должны использовать следующий код, я сделал незначительные изменения в вашей попытке.

awk '
FNR==NR{
  val=$1
  $1=""
  sub(/^ +/,"")
  seen[val]=$0
  next
}
$2 in seen{
  print $2,seen[$2],$1
  b[$2]
  next
}
END{
  for(i in seen){
    if(!(i in b)){
      print i,seen[i]
    }
  }
}
' file2.txt file1.txt | sort -V

Вывод будет следующим.

1 John Lennon A
2 Mariah carey
3 Cool & The Gang C
4 Westlife
5 Red Hot Chili Peppers E

Проблема с Попытка кода OP:

  • OP создает индекс для видимого массива как $ 1 (это правильно), НО делает значение ТОЛЬКО $ 2, что НЕ правильно, потому что $ 2 будет ловить только John ИЛИ Mariah и т. Д.
  • По этой причине попытка OP НЕ дает полного вывода.
  • Также OP использует для проверки индекс $ 1 Input_file1 (file1.txt) если он присутствует в видимом массиве или нет, он должен быть там $ 2.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...