Чи є інструмент, який може отримати рядки, який містить файл A, але файл B не має? Я міг би зробити трохи простий сценарій, наприклад, з perl, але якщо щось подібне вже існує, я з цього часу заощаджую свій час.
Чи є інструмент, який може отримати рядки, який містить файл A, але файл B не має? Я міг би зробити трохи простий сценарій, наприклад, з perl, але якщо щось подібне вже існує, я з цього часу заощаджую свій час.
Відповіді:
Так. Стандартний grep
інструмент пошуку файлів за текстовими рядками може використовуватися для віднімання всіх рядків в одному файлі від іншого.
grep -F -x -v -f fileB fileA
Це працює, використовуючи кожен рядок у fileB як візерунок ( -f fileB
) та обробляючи його як звичайний рядок, який відповідає (а не звичайний регулярний вираз) ( -F
). Ви змушуєте збіг відбуватись у всій лінії ( -x
) та друкуєте лише ті рядки, які не відповідають ( -v
). Тому ви друкуєте рядки у fileA, які не містять тих самих даних, що й будь-які рядки у fileB.
Мінус цього рішення полягає в тому, що він не враховує порядок рядків, і якщо у вашому введенні є дублікати рядків у різних місцях, ви можете не отримати те, що очікуєте. Рішенням цього є використання реального інструменту порівняння, такого як diff
. Ви можете зробити це, створивши файл diff зі значенням контексту на 100% рядків у файлі, а потім розібрав його лише для рядків, які будуть видалені, якщо перетворити файл A у файл B. (Зверніть увагу, ця команда також видаляє diff форматування після отримання правильних ліній.)
diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
-u
насправді приймає параметр числа, доки за ним не пробіл. Перевага способу, який я мав раніше, полягає в тому, що він буде працювати зі значенням або без нього, так що ви можете використовувати щось у тій підпрограмі підкоманд, яка не повертається. Верхня літера "-U", з іншого боку, вимагає аргументу.
diff
трубопровід працює ласощі спасибі.
grep
потрібно. Приклад:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
є те, що положення у файлі враховується.
Відповідь багато в чому залежить від типу та формату файлів, які ви порівнюєте.
Якщо файли, які ви порівнюєте, відсортовані текстові файли, то інструмент GNU, написаний Річардом Сталлманом та Девідеєм Маккензі, comm
може викликати фільтрацію, яку ви шукаєте. Він входить до основних ядер.
Скажімо, у вас є два такі файли:
$ cat a
1
2
3
4
5
$ cat b
1
2
3
4
5
6
Рядки у файлі b
, які відсутні у файлі a
:
$ comm <(sort a) <(sort b) -3
6
comm
; на жаль, comm
потрібні відсортовані файли
<()
? Це працює, і я розумію, але чи є назва цієї дивацтва?
<()
також відомий як процес заміщення .
comm
Спочатку був написаний приблизно в 1973 р. ким-то в Bell Labs, а не в rms. Ви маєте на увазі реалізацію GNU, яка надійшла набагато пізніше. Протягом багатьох років було багато різних реалізацій утиліт Unix.
від stackoverflow ...
comm -23 file1 file2
-23 пригнічує рядки, які знаходяться в обох файлах, або лише у файлі 2. Файли мають бути відсортовані (вони є у вашому прикладі), але якщо ні, спочатку переведіть їх через сортування ...
Дивіться сторінку людини тут
Методи grep і comm (з сортуванням) займають багато часу для великих файлів. SiegeX і ghostdog74 поділилися двома чудовими методами awk для витягування рядків, унікальних для одного з двох файлів на Overflow Overck:
$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
Якщо файли великі і у вас немає спеціального замовлення на ваші записи, grep триває дуже багато часу. Швидка альтернатива була б
sort file1 > 1
sort file2 > 2
diff 1 2 | grep "\>" | sed -e 's/> //'
[file2-file1 результати на екрані, передача файлів тощо]
Зміна >
до <
отримають протилежне віднімання.rm 1 2