У меня есть большой файл A (состоящий из электронных писем), одна строка для каждого письма. У меня также есть другой файл B, который содержит другой набор писем.
Какую команду я бы использовал, чтобы удалить все адреса, которые появляются в файле B, из файла A.
Итак, если файл A содержал:
A
B
C
и файл B содержал:
B
D
E
Тогда файл A должен остаться с:
A
C
Теперь я знаю, что это вопрос, который, возможно, задавался чаще, но я нашел только одну команду в сети, которая выдала мне ошибку с неправильным разделителем.
Любая помощь приветствуется! Кто-то наверняка придумает умную однострочку, но я не эксперт по оболочкам.
Ответы:
Если файлы отсортированы (они есть в вашем примере):
-23
подавляет строки, которые есть в обоих файлах или только в файле 2. Если файлы не отсортированы, направьте их черезsort
сначала ...Смотрите страницу руководства здесь
источник
comm -23 file1 file2 > file3
выводит содержимое в файл1, а не в файл2, в файл3. И тогдаmv file3 file1
, наконец, очистить избыточное содержимое в file1.comm -23 file1 file2 | sponge file1
. Очистка не требуется.grep -Fvxf <lines-to-remove> <all-lines>
Пример:
Вывод:
Объяснение:
-F
: использовать буквенные строки вместо BRE по умолчанию-x
: рассматривать только совпадения, соответствующие всей строке-v
: печать не соответствует-f file
: взять шаблоны из данного файлаЭтот метод медленнее для предварительно отсортированных файлов, чем другие методы, поскольку он более общий. Если скорость имеет значение, смотрите: Быстрый способ поиска строк в одном файле, которые не находятся в другом?
Вот быстрая автоматизация bash для работы в потоке:
GitHub вверх по течению .
использование:
Смотрите также: /unix/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another
источник
awk на помощь!
Это решение не требует отсортированных входных данных. Вы должны предоставить fileB первым.
возвращается
Как это работает?
Обратите внимание, что теперь это можно использовать для удаления слов из черного списка.
с небольшим изменением он может очистить несколько списков и создать очищенные версии.
источник
A\nC
, сначала записать временный файл и перезаписать исходный файл... > tmp && mv tmp fileA
fileB
он не пустой (длиной 0 байт), потому что если это так, вы получите пустой результат вместо ожидаемого содержимогоfileA
. (Причина:FNR==NR
применимо к томуfileA
времени.)Другой способ сделать то же самое (также требует отсортированного ввода):
В Bash, если файлы предварительно не отсортированы:
источник
Вы можете сделать это, если ваши файлы не отсортированы
--new-line-format
предназначен для строк, которые находятся в файле b, но не в a,--old-..
предназначен для строк, которые находятся в файле a, но не в b,--unchanged-..
предназначен для строк, находящихся в обоих.%L
делает так, чтобы строка печаталась точно.Больше подробностей
источник
comm
команду.comm
требует сортировки файлов, поэтому, если они отсортированы, вы также можете использовать это решение. Вы можете использовать это решение независимо от того, отсортирован файл или нетЭто уточнение хорошего ответа @ karakfa может быть заметно быстрее для очень больших файлов. Как и в случае с этим ответом, ни один файл не должен быть отсортирован, но скорость обеспечивается за счет ассоциативных массивов awk. Только файл поиска хранится в памяти.
Эта формулировка также допускает возможность использования только одного конкретного поля ($ N) во входном файле для сравнения.
(Другое преимущество этого подхода заключается в том, что он легко модифицирует критерий сравнения, например, обрезая начальные и конечные пробелы.)
источник
Вы можете использовать Python:
источник
Ты можешь использовать -
diff fileA fileB | grep "^>" | cut -c3- > fileA
Это будет работать для файлов, которые также не отсортированы.
источник
Для удаления общих строк между двумя файлами вы можете использовать команду grep, comm или join.
Это отображает строки из файла1, которые не соответствуют ни одной строке в файле2.
Это отображает строки из файла1, которые не соответствуют ни одной строке в файле2.
источник