Найти - Пользователи
Полная версия: Удаление из списка элементов по регулярному выражению
Начало » Python для новичков » Удаление из списка элементов по регулярному выражению
1 2
N.
Доброго времени.
Задача: парсинг больших лог файлов (в несколько Гб).
В скрипте задаю пул нужных адресов (переменная pull). Обрабатывая лог, я хочу получить на выходе файл, где не должно быть адресов, кроме тех, что есть в pull.
Непроблемные места я убрал, чтобы не нагружать лишним:
 pull = ""
log = "путь_к_логу"
output = "путь_к_обработанному_файлу"
with open(log) as inp, open(output, "w") as out:
    spis = inp.readlines()
    for s in spis:
        if not re.search('[{}]'.format(pull), s):
              spis.remove(s)
Однако в итоге, я получаю часть адресов, которые совпадают с паттерном не полностью, например, может быть разрешенный набор “abcd”, а после обработки я получу “abcde”. Понятно, что он совпадает, но не полностью. Раньше я организовывал проверку через цикл поэлементно без регулярного выражения. К регулярным выражениям пришел, т.к. подсказали, что так код будет быстрее выполняться. Подскажите, пожалуйста, как организовать проверку по регулярному выражению, чтобы в итоге, каждый элемент состоял только из разрешенных в pull?
N.
Если вдруг я непонятно объяснил, то вот пример на простом списке:
 import re
l = ["123", "1aa", "@a1", "ЙЙЙ", "q2й", "$$$", "bbй"]
pull = "a2b"
for i in l:
     if not re.search('[{}]'.format(pull), i):
         l.remove(i)
print(l)
'123', '1aa', '@a1', 'q2й', 'bbй'
После удаления в каждом элементе списка есть что-то из pull, но так же есть и ненужное. Нужно оставить _только_ те элементы, которые содержать _только_ то, что есть в пул.
FishHook
N.
Ваша ошибка распространена необычайно, нельзя перебирать список и одновременно удалять из него элементы.
Смотрите
 l = [1, 2, 3, 4, 5]
for i in l:
    l.remove(i)
print(l)
Можно ожидать, что после выполнения цикла список получится пустой, однако это не так, попробуйте выполнить этот код. Кода вы удаляете элемент с индексом 0 (то есть единицу), следующий элемент в цикле должна быть двойка, но цикл получает значение счетчика 0 + 1 = 1, а элемент с индексом 1 это УЖЕ (после удаления единицы) не двойка, а тройка. Таким образом 2 и 4 выпадают из цикла.

Общий совет здесь такой: если вы не работаете с очень большими массивами данных, не нужно изменять изначальный список, лучше создать новый, то есть вместо того чтобы удалять элемент из списка А, вы просто не добавляйте его в Б.
N.
FishHook
N.Ваша ошибка распространена необычайно, нельзя перебирать список и одновременно удалять из него элементы.Смотрите
В том то и дело, что работаю с большими лог файлами и потому пытаюсь уйти от предыдущего способа с пересобираением нового списка в цикле. Способ достаточно медленный и приходится всегда расчитывать свободное место под еще один лог, из которого будет происходить удаление. Получается, в моем случае не выйдет решить проблему регулярными выражениями?
FishHook
А вы отсортированные данные не в список пишите, а сразу в файл
N.
FishHook
А вы отсортированные данные не в список пишите, а сразу в файл
Я сейчас так и делаю. Есть исходный лог, я его сортирую и записываю в тот самый output из кода в 1 посте. Получается 2 лога: исходный и отсортированный. Я надеялся, что есть возможность сделать скрипт, который будет работать с регулярками как потоковый редактор sed в linux, который вносит изменения в тот же файл, без необходимости создавать новый.
N.
Ну и вопрос с самой регуляркой еще остается для меня открытым. Если даже придется оставить вариант с двумя файлами, как правильно организовать проверку по регулярке, как описано в посте 2?
FishHook
N.
вносит изменения в тот же файл, без необходимости создавать новый
А на чем зиждется ваша уверенность, что это тот же самый файл? Если я создам временный файл, потом удалю старый, а временный переименую будет как будто старый файл.
Rodegast
> К регулярным выражениям пришел, т.к. подсказали, что так код будет быстрее выполняться.

Обманули тебя. Регулярки намного медленнее методов строк.
N.
Rodegast
Обманули тебя. Регулярки намного медленнее методов строк.
Жаль… Тогда остановлюсь на старом варианте. Но на будущее все же поинтересуюсь, как применить регулярку для поиска элементов, полностю состоящих из заданных? Я еще раз перечитал учебник и документацию и не нашел методов, которые бы такое делали. Search ищет любой совпадение, findall только в заданном порядке и только полное совпадение с исходником. Грубо говоря, имея список из: “1”, “2”, “12”, “21”, “31”, “32”, “3” и паттерн “12”, как получить все элементы, которые состоят только из “1” и “2” вне зависимости от порядка и кол-ва повторений с помощью регуляки? Я понимаю как это сделать через обычный цикл вроде
 list1 = [...]
pattern = ""
def check(list1):
    for words in list1:
        for chars in words:
            if chars not in pattern:
                return False
    return True
но может быть можно избежать перебора каждого символа в каждом элементе списка?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB