Что относительно этого?
awk -F, 'NR==FNR{old[$0];next} $0 in old{delete old[$0];next} 1 END{for(line in old) print line}' old.txt <(sort -u new.txt) | sort
Давайте разломаем его на части.
-F,
tells awk to use a ,
as a field separator.
NR==FNR{old[$0];next}
- In cases where NR (record/line number) matches the line number in the current file (that is, while we're reading the first input file), stores the whole line as the index of an associative array, then jumps to the next record.
$0 in old{delete old[$0];next}
- Now we're reading the second file. If the current line is in the array, delete if from the array and move on. This address condition #1 in your question.
1
- short hand in awk for "print the line". This addresses part of condition #3 in your question by printing unique lines from the second file.
END{...}
- this loop prints everything that wasn't deleted from the array. This addresses the other part of condition #3 by printing unique lines from the first file.
<(sort -u new.txt)
- uniques the input of new.txt. If you know that new.txt is unique already, you can remove this bash dependency.
| sort
sorts the output, "grouping" things per condition #2 in your question.
Типовая продукция:
$ cat old.txt
one,two,three,four,five,six
un,deux,trois,quatre,cinq,six
$ cat new.txt
one,two,three,four,FIVE,SIX
un,deux,trois,quatre,cinq,six
en,två,tre,fyra,fem,sex
$ awk -F, 'NR==FNR{old[$0];next} $0 in old{delete old[$0];next} 1 END{for(line in old) print line}' old.txt new.txt | sort
en,två,tre,fyra,fem,sex
one,two,three,four,FIVE,SIX
one,two,three,four,five,six
$
Обратите внимание, что линия на французском языке была дублирована, таким образом пропущена. Все остальное было напечатано с двумя английскими линиями, "сгруппированными", сортировав.
Обратите внимание также, что это решение страдает на очень больших файлах, потому что все old.txt загружаются в память как множество. Альтернатива, которая могла бы работать на вас, будет этим:
$ sort old.txt new.txt | awk '$0==last{last="";next} last{print last} {last=$0} END{print last}' | sort
en,tva,tre,fyra,fem,sex
one,two,three,four,FIVE,SIX
one,two,three,four,five,six
$
Идея здесь состоит в том, что вы просто берете ВСЕ входные данные из своих файлов, сортируете их, затем используйте awk сценарий, чтобы пропустить повторенные линии и напечатать все остальное. Тогда сортируйте продукцию. Это работает над потоком, насколько awk затронут, но быть предупрежденным, что для очень большого входа, ваш вид
команда все еще должна загрузить данные в файлы временного секретаря и/или память.
Кроме того, как есть это второе решение терпит неудачу, если конкретная линия повторяется несколько раз. Таким образом, если это существует однажды в old.txt и дважды в new.txt. Вы нуждаетесь к уникальному в своих входных файлах или приспосабливаете сценарий к той ситуации.