Ответы пользователя по тегу Регулярные выражения
  • Как вычленить из текста ФИО на python, при том что конкретных шаблонов нет?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    В общем случае эта задача не решается на 100% по определению.
    Вы говорите, что вокруг фамилий у вас произвольный текст, а это значит, что среди этого текста попадаются слова, которые чем-то похожи на ФИО, но не ФИО, или имя отчество, без фамилии, или что-то вроде "светкин василёк Игоревич". Можно это считать таким экзотическим ФИО, или отчество тут просто отдельно стоит и искать его не надо?
    В любом случае схема решения примерно такая. Если у вас есть знаки препинания, то можно разбить по ним фрагменты текста, ФИО не разделяется знаками препинания (кроме дефиса), но дефис отличается от тире пробелами по бокам.
    Далее у вас есть цепочки слов. Если в цепочке N слов, то в ней, можно сказать, N-2 кандидата на ФИО.
    Каждая трока-кандидат на ФИО может быть проклассифицирована по ряду признаков, свидетельствующих в пользу того, является ли эта тройка ФИО. Осталось только определить набор признаков и веса этих признаков. Каждый признак определяет два показателя: 1) насколько этот признак добавляет шансов тройке быть ФИО; 2) на сколько несовпадение по этому признаку отнимает шансов быть ФИО. Показатели определяются от нуля до 1 и перемножаются. Подбор признаков и их показателей будет настройкой вашего классификатора.
    Тут дальше можно двигаться разными путями.
    Часть детектов вы сможете надёжно определять по окончанию отчества.
    Часть признаков у вас будут словарными словами, которые, по вашему, не могут быть именем и\или фамилией.
    На этом этапе уже будет довольно хорошая детекция. Вопрос что вам важнее, отсутствие false positive, или отсутствие false negative.
    Так же по-разному может повезти с входными данными. Если у вас много "ловушек" в виде разбросанных по тексту бесхозных отчеств, если у вас много очень странных имён... в общем тут вам никто не выдаст идеальное решение. При отсутствии четкого ТЗ результатом будет расплывчатое ХЗ.
    В целом обычно на настройку таких классификаторов под текст на первое время сажают людей. У нас сейчас есть ChatGPT и ему, думаю, вполне можно скидывать наборы имён, чтобы он вычеркивал те, которые вряд ли именами являются. Если вы приняли, что какое-то слово не может являться именем, или фамилией, то такое решение хорошо бы кэшировать, а затем для консистентности придерживаться аналогичного в других случаях.

    Странная у вас задача, сударь. Выглядит как учебная. В этом случае рассуждений вроде приведенных мной здесь хватило бы для успешного ответа на собеседовании.
    Ответ написан
    2 комментария
  • Какую регулярку использовать?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    В большинстве случаев не стоит использовать регекспы для работы с html-разметкой. Для этого есть другие средства, например xpath-селекторы или обход дерева тегов скриптом на питоне.
    Если нужно поправить ссылки, то тут можно и регекспами, ведь ссылки, как правило, различаются внутри, часто можно по префиксу в URI понять о какой ссылке речь.
    Обратите внимание на библиотеку beautiful soup. Там есть всё необходимое для конвертации ваших статей.
    Более детальных рекомендаций не дам ввиду ограниченности примеров, которые вы привели. Надо показывать примеры как есть, ведь из-за отсутствия опыта вы опускаете важные существенные детали и подробности. Например, структуру URL в ссылках, стили и классы в тегах...
    Ответ написан
    9 комментариев
  • Как написать регулярное выражение?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Очень плохая идея парсить html регулярными выражениями. Они не для этого предназначались. Есть специальные инструменты для этой цели, которые извлекают данные по xpath.
    Ответ написан
    Комментировать
  • Как мне сделать отрицание регулярного выражения?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вот так мы найдём все строки, которые не являются девятизначными номерами.
    ^(?!\d{9}$).*$
    Вот пример: https://regex101.com/r/4RWJFc/1
    Ответ написан
    Комментировать
  • Как составить регулярку с батником?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    А зачем тут регекспы? Отличаться-то будет только искомая подстрока. Отрезайте нужное количество символов по бокам и всё.
    Ещё в батниках есть синтаксис. который позволяет заменять подстроку:
    set str="any_text/UC5qUbVE66mMu9kvsn_ki5yQ"
    set str=%str:any_text=%

    Чтобы заменить конкретный кусок урла, придётся экранировать символы, но попробовать мне негде, вокруг нет винды, так что экспериментируйте.

    UPD:
    После разъяснения автором стало понятнее. Вот решение:
    py -x "'channel/'+x.split('/')[5]" < t1.txt > t2.txt

    Утилита py стандартная, ставится в рамках пакета pythonpy, удобна для конвейерной обработки питоновскими однострочниками файловых потоков.
    Ответ написан
    6 комментариев
  • Что нужно установить и сделать, чтобы начать пользоваться?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Консоль линукса и команду grep. Там много аргументов и возможностей.
    Команда sed - это фактически консольный потоковый текстовый редактор. Очень мощный, но сложный в понимании. Проще освоить питон и пользоваться для ваших целей вот такими однострочниками:
    $ man py | py 're.compile("\w{10,}").findall(sys.stdin.read())'
    completion
    expression
    DESCRIPTION
    expression
    interpreter
    compatible
    expression
    expression
    arithmetic
    automatically
    distribution

    Что тут происходит:
    Берём справку по консольной тулзе pythonpy, конвейером передаём в эту утилиту, которая выполнит кусочек питоновского кода. Код читает всё, что приходит на вход и находит все слова длинной 10 и более символов.
    Ответ написан
    Комментировать
  • Как правильно составить регулярное выражение?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вы непонятно формулируете задачу.
    Только буквы, а потом только цифры, а затем точка, пробел и дефис? Или это может быть вперемежку?
    Если последовательно, то так и пишите:
    [a-zA-Z]+[0-9]+\.\s-
    Если это всё нужно вперемежку, то ваш вариант годится.
    Ответ написан
  • Почему не работает регулярное выражение?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Смотрите. У вас в файле абзацы по-другому устроены и при копировании они заменяются на виндовый формат.
    Ваш регексп можно чуточку упростить:
    ^(.{0,7})\r\n|^([0-9]{8})\r\n
    Для того, чтобы регексп работал на данном файле с теми абзацами что там есть, нужно использовать \n вместо \r\n.
    Ещё раз...
    В файле абзацы состоят из символа "OA". Ваш регексп в качестве абзацев ожидает пары "OD 0A". При копировании\вставке текста в редакторе в новый файл абзацы заменяются на станартные для данной ОС и данного редактора. Ваш редактор поддерживает юникс-формат абзацев, но по умолчанию использует именно виновый из двух символов. Вы можете сделать регексп универсальным поставив вопросик после символа \r.
    Ответ написан
    6 комментариев
  • Как проверить международный номер телефона на валидность?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    По идее стандарт номера телефона, по которому отовсюду можно позвонить такой: "\+\d{11}".
    Проблемы могут возникнуть с местными городскими соращенными номерами, там может быть и 5 цифр и 6 и 7 без кода города. Но если вы собираете номера телефонов по всему миру. то код города и страны вам все равно нужен,а значит 11-значный номер в любом случае будет правильным.
    В разных местах по-разному ринято группировать цифры скобочками и дефисами. Но это к формату самого номера не относится, номер начинается с плюса и имеет 11 цифр. всё.
    Из него взяв первую одну или больше цифр можно получить код страны, потом. для местных номеров, код региона, потом местный номер, но это лишнее, мне кажется. Берите одиннадцать цифр и всё.
    Для разных стран можно предлагать пользователю разные форматы отображения и группировки цифр номера, но это уже прям можно сказать лишнее. Просто при вводе гнорируйте все кроме цифр, а плюс оставьте зафиксированным, чтобы люди догадались, что номер нужен в полном международном одиннадцатизначном формате.
    Ответ написан
    4 комментария
  • Как запретить ввод пробелов, скобок и тире в поле?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    https://regex101.com/r/nV9ZLS/1
    ^[^\s()-]*$
    Первая "крышка" означает, что это начало строки. Последний "доллар" означает конец строки.
    Между ними любое (0 или более символов) из множества, описанного в квадратны скобках.
    В квадратных скобках крышка означает, что множество инвертировано. То есть допускаются любые символы, кроме перечисленных.
    То есть, данное множество представляет собой НЕ: пробел, скобки и минус, но любые другие символы.
    Ответ написан
    1 комментарий
  • Как сделать маску в far manager?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вот винды у меня лет 5 уже нет и ни о чем кроме фара не жалею.
    Полез вот и специально скомпилировал его себе на убунту.
    Там есть очень хорошая справка Вот она русским по бирюзовому как раз про регекспы:
    5f7cc2d58727d995090457.png
    Ответ написан
    Комментировать
  • Как с помощью regexp удалить теги, у которых есть атрибут class и style, вместе с контентом?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Плохая идея регекспами такое парсить. Лучше воспользйтесь lxml или любым таким парсером.
    Проблема в том, что у вас внтури такого тега может (теоретически) быть непредсказуемая вложенность других тегов. Рекурсивные и контекстные вещи регекспами делаются очень неудобно.
    Разбейте весь текст запроса на лексемы, например так:
    re.split('<|>')
    И вы получите сисок, где нулевой и все четные элементы - это фрагменты текста, а все нечетные по индексу элементы - это содержимое тегов. Содержимое закрывающих тегов можно распозать по слешу.
    Дальше нужно запрограммировать конечный автомат с двумя состояниями, которому можно скормить этот список, а вернёт он такой же список, но отфильтрует ненужные элементы.
    Грубо говоря, в первом состоянии вы перебираете входной список и когда встречаете нечетный эелемент (тег), начинающийся со слова span и содержащий атрибуты, сбрасываете счетчик в ноль и переходите во творое состояние.
    Во втором - перебираете се элементы и инкрементируете счетчик каждый раз когда попадается открывающий тег, и декрементируете когда попадается закрывающий (нечетный элемент, начинающийся начинается со слеша). Если счетчик снова стал нулём, переходите в первое состояние.
    На выход следует пропускать только элементы находясь в первом состоянии. Второе состояние подавляет выхлоп.
    def f(lexems): 
        state, deep = 0, 0 
        for i, lex in enumerate(lexems): 
            if state == 0: 
                if i%2 and lex.startswith('span '): 
                    state = 1 
                    deep = 1 
                else: 
                    yield f'<{lex}>' if i%2 else lex 
            else: 
                if i%2: 
                    deep += -1 if lex.startswith('/') else 1 
                if deep == 0: 
                    state = 0
    Ответ написан
    Комментировать
  • Как исключить ввод кириллицы, спецсимволов и пробелов?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    [a-zA-Z0-9]+
    Но у вас плохие требования к паролю.
    Они выдают непрофессионализм разработчиков, которые внедряют такие требования.
    Это признак того, что пароль лежит в открытом (не хешированном) виде в БД.
    Это провоцирует делать слабые пароли.
    Это выглядит как поделка студентов.

    Если и вводить ограничения, то минимальные:
    - пароль должен быть не пустым. Всё.

    Однако следует делать предупреждения если:
    - пароль содержит кириллицу, или любые символы, которые сложно набрать на любой произвольной клавиатуре. Большая проблема пароль с юникод-символами, если вы хотите ввести его на смартфоне. Большая проблема с кириллицей, если вы хотите войти с компа в турции в отпуске, потеряв, к примеру, телефон.
    - пароль слишком короткий;
    - хеш пароля находится в списке наиболее распространённых паролей;
    - пароль выглядит как набранный с инвертированным капс-локом.

    Эти предупреждения должны быть заметны, но не должны запрещать создать такой пароль. Обсуждать можно только то, что касается списка самых распространённых паролей, скажем тысячи самых популярных. Ну и короткие (меньше 6 знаков).
    Пароль следует хешировать с только что сгенерированной солью. Хранить соль нужно рядом с хешем. Также рядом можно указать название алгоритма хеширования. Прямо в одной строке. Это не снизит безопасность, зато избавит вас от проблем связанных с переходом на новые алгортимы хеширования.
    Ответ написан
  • Как написать такую валидацию в regex?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    https://regex101.com/r/sXBK61/1
    ^[A-Za-zА-Яа-я]+([\-`][A-Za-zА-Яа-я]+)*$
    Ответ написан
    Комментировать
  • Поможете с "cb = lambda m: random.choice(m.group(1).split('|'))"?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Передаётся вот здесь:
    rgx.sub(cb, s)
    Все сопоставления регекспу будут подаваться этой функции в аргумент.
    cb = lambda m: \     # Это лямбда-функция с одним аргументом по имени m
        random.choice(   # результат функции вычисляется методом случайного выбора из
            m.group(1)   # текста (сопоставленного с первой скобкой регекспа)
            .split('|')  #  разбитого по символу "|"
        )

    Регексп rgx = re.compile('\{([^{}]*)\}') находит куски текста в фигурных скобках и m.group(1) будет соответствовать этому куску при каждом вызове лямбды.
    Ответ написан
  • Как решить проблему с условием вывода и регулярными выражениями в Python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    1)
    Попытки убрать блок else, либо заменить "Нет вхождения" на pass или None - выдают ошибку.

    a if q else b - это тернарный оператор. У него три аргумента (a, b, q) и результатом будет a или b в зависимости от истинности q.
    pass там по синтаксису не подойдёт, поскольку это не значение, а ключевое слово.
    Вам нужно вычислить выражение и результатом должно быть что-то что можно передать в print(). Если по else вы укажете пустую строку "", то print её напечатает. Не знаю устроит ли вас пустой абзац в консоли. Если нет, то смотрите решение, предложенное выше.

    2) в предыдущем решении вы могли не заметить, но регекспы соединены через "|". Это сработает не для всех регекспов. Нужно быть осторожнее с такой конкатенацией. Вообще с регекспами надо поосторожнее. В большой силе большая ответственность.
    Можно сделать цикл и поискать каждый регексп по отдельности. Так вам проще сохранить контроль над тем, что именно вы нашли и как на это реагировать.
    Ответ написан
    1 комментарий
  • Как исключить строки из выборки?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    [\\/]node_modules[\\/]((?!blueimp-file-upload|jquery-ui).*)[\\/]
    Ответ написан
    Комментировать
  • Как вытащить из ссылки слово REGEX?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вот так?
    Я вас видимо не очень понял. Вот такой вот вариант еще ловите: https://regex101.com/r/5FoQLB/4
    Ответ написан