4

Какой самый простой способ удалить строки из одного файла, совпадающие со строками из другого файла? Например, если у меня есть следующие файлы:

file1.csv:

u2@domain.com

file2.csv:

1,u1@domain.com,somehash1
2,u2@domain.com,somehash2
3,u3@domain.com,somehash3

В результате я хотел бы получить file3.csv:

1,u1@domain.com,somehash1
3,u3@domain.com,somehash3

Какой самый быстрый способ решить эту задачу? Эти файлы имеют размер несколько ГБ.

6 ответов6

7

grep -v -F -f file1.csv file2.csv > file3.csv кажется самым простым. Но сначала вы должны выполнить тесты производительности с небольшими файлами. (Я согласен с комментарием Соандоса о том, что для таких больших файлов может потребоваться специальное решение.)

3
awk -F, '
  FILENAME == ARGV[1] {to_remove[$1]=1; next}
  ! ($2 in to_remove) {print}
' file1.csv file2.csv > file3.csv

У вас должно быть достаточно памяти для чтения в file1 сразу.

Вот еще один вариант: join

$ join -t , -v 2 -1 1 -2 2 file1.csv file2.csv
u1@domain.com,1,somehash1
u3@domain.com,3,somehash3

Однако из справочной страницы «Важно: FILE1 и FILE2 должны быть отсортированы по полям соединения». так что учтите это в своем решении.

1

Вы можете перебрать каждую строку в файле file1 и получить соответствующие строки из файла file2?

cp file2.csv file3.csv
cat file1.csv | while read line; do
    grep -v ${line%?} file3.csv > temp.csv
    cat temp.csv > file3.csv
done
rm -f temp.csv

Непроверенные.

Изменить: протестировано, кажется, работает нормально. Просто убедитесь, что у вас есть завершающий символ новой строки в file1.

1

Должен ли file1.csv оставаться неизменным?

sed 's|.*|/^&.*/d|' file1.csv > file1.sed
sed -f file1.sed file2.csv > file3.csv 

Я не знаю, сколько памяти он потребляет. AFAIK, он будет каждый раз проверять файл целиком на всем входе (2.csv).

Если входные данные отсортированы, а шаблоны также отсортированы, вы можете реализовать более быстрое решение.

0

Это не нуждается в кодированном решении.«Если сначала отсортировать строки, сложность алгоритма уменьшается на несколько порядков.

Посмотрите этот ответ для лучшей производительности, как с точки зрения процессорного времени и памяти:

https://stackoverflow.com/questions/4366533/remove-lines-from-file-which-appear-in-another-file

0

Убедитесь, что file3.csv существует (и он пуст)

echo > file3.csv
diff file1.csv file2.csv | patch file3.csv

И вуаля!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .