Поиск дополнения к набору в Unix
Учитывая это два файла:
$ cat A.txt $ cat B.txt
3 11
5 1
1 12
2 3
4 2
Я хочу найти номер строки, который находится в "НО НЕ" в B. Какая команда unix для него?
Я попробовал это, но, похоже, не удалось:
comm -3 <(sort -n A.txt) <(sort -n B.txt) | sed 's/\t//g'
5 ответов
comm -2 -3 <(sort A.txt) <(sort B.txt)
надо делать что хочешь, если я тебя правильно понял.
Редактировать: На самом деле, comm
файлы должны быть отсортированы в лексикографическом порядке, так что вы не хотите -n
в вашем sort
команда:
$ cat A.txt
1
4
112
$ cat B.txt
1
112
# Bad:
$ comm -2 -3 <(sort -n B.txt) <(sort -n B.txt)
4
comm: file 1 is not in sorted order
112
# OK:
$ comm -2 -3 <(sort A.txt) <(sort B.txt)
4
Ты можешь попробовать это
$ awk 'FNR==NR{a[$0];next} (!($0 in a))' B.txt A.txt
5
4
Обратите внимание, что решение awk работает, но сохраняет дубликаты в A (которых нет в B); решение python дублирует результат
также обратите внимание, что comm
не вычисляет истинную разность множеств; если линия повторяется в A, и повторяется в B меньше, comm
оставит "лишнюю" строку (и) в результате:
$ cat A.txt
120
121
122
122
$ cat B.txt
121
122
121
$ comm -23 <(sort A.txt) <(sort B.txt)
120
122
если это поведение нежелательно, используйте sort -u
удалить дубликаты (только дубли в вопросе А):
$ comm -23 <(sort -u A.txt) <(sort B.txt)
120
Недавно я написал программу под названием Setdown, которая выполняет операции Set из клима.
Он может выполнять операции над множествами, написав определение, подобное тому, что вы написали бы в Makefile:
someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection
Это довольно круто, и вы должны это проверить. Лично я не рекомендую использовать специальные команды, которые не были созданы для выполнения заданий. Он не будет работать хорошо, когда вам действительно нужно выполнить много операций над множествами или если у вас есть какие-либо операции над множествами, которые зависят друг от друга. Кроме того, setdown позволяет вам писать операции над множествами, которые зависят от других операций над множествами!
Во всяком случае, я думаю, что это довольно круто, и вы должны полностью проверить это.
Примечание: я думаю, что Setdown намного лучше, чем comm просто потому, что Setdown не требует правильной сортировки входных данных. Вместо этого Setdown отсортирует ваши входные данные и использует внешнюю сортировку. Так что он может обрабатывать большие файлы. Я считаю это большим преимуществом, потому что количество раз, которое я забыл сортировать файлы, которые я передал в comm, неисчислимо.
Вот еще один способ сделать это:
join -v1 <(sort A.txt) <(sort B.txt)
Из документации по
join
:
'-v номер-файла' Вывести по строке для каждой нежелательной строки в файле номер-файла ('1' или '2') вместо обычного вывода.