У меня есть CSV-файл users.csv
со списком userNames, userID и другими данными:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"Paul McCartny", 30923833, "left", "black"
"Ringo Starr", 77392318, "right", "blue"
"George Harrison", 72349482, "left", "green"
В другом файле у toremove.txt
меня есть список идентификаторов пользователей:
30923833
77392318
Есть ли умный, эффективный способ удалить все строки из users.csv
файла, которые содержат идентификаторы в toremove.txt
? Я написал простое приложение на Python для анализа двух файлов и записи в новый файл только тех строк, которые не найдены в нем toremove.txt
, но он чрезвычайно медленный. Может быть, некоторые sed
или awk
магия может помочь здесь?
Это желаемый результат, учитывая приведенные выше примеры:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"
linux
command-line
text-processing
dotancohen
источник
источник
users.csv
строк файла и n для строкtoremove.txt
. Я не совсем уверен, как это сделать с меньшей сложностью. Суть его заключается в :for u in users: if not any(toremove in u): outputfile.write(u)
. Я могу опубликовать его в Code Review.toremove.txt
, сохранив записи как ключи . Итерируйте users.csv, печатая те, в которых идентификатор не указан. Вы получаете O (n) для обработки какtoremove.txt
иusers.csv
, так и O (n) для использования памятиtoremove.txt
(что, вероятно, относительно мало)Ответы:
С помощью
grep
вы можете сделать:С
awk
:источник
awk
Решение очень чувствительно к файлам быть отформатированы точно , как показано в этом вопросе. Наиболее очевидно, что если имя представляет собой всего одно слово / токен (т. Е. Оно не содержит пробелов; например,"Bono"
) или содержит более двух токенов (т. Е. Оно содержит более одного пробела; например,"Sir Paul McCartney"
), оно будет проходить, даже если совпадения идентификаторов пользователей. Менее очевидно, то же самое происходит, если между первой запятой и идентификатором пользователя нет пробела или если имеется несколько пробелов (например,"John Lennon", 90123412, …
).awk
решениеgrep
Вот
awk
ответ Gnouc , измененный, чтобы быть невидимым :Поскольку он использует только запятые (а не пробелы) в качестве разделителей,
$1
is"John Lennon"
,$2
is90123412
(с начальным пробелом) и т. Д. Поэтому мы используемgensub
для удаления любое количество начальных пробелов,$2
прежде чем проверять, был ли он (идентификатор пользователя) вtoremove.txt
файле.источник
ОК, путь ruby: если у вас есть список строк в файле, и вы хотите удалить все строки из другого файла, которые даже содержат любую строку в первом файле (в этом случае удаление «file2» из «file1») файла ruby :
к сожалению, при большом «удаляемом» файле это, по-видимому, ухудшает сложность до O (N ^ 2) (я предполагаю, что регулярному выражению есть над чем поработать), но все же может оказаться полезным для кого-то там (если вы хочу больше, чем удаление полных строк). Это может быть быстрее в некоторых случаях.
Другой вариант, если вы стремитесь к скорости, - это использовать тот же механизм проверки хеша, но тщательно «проанализировать» строку на предмет соответствия строк, а затем сравнить их с вашим хешем.
В ruby может выглядеть так:
См. Также ответ Скотта, он похож на ответы на awk, предложенные здесь, и избегает сложности O (N ^ 2) (фу).
источник