избегать регулярных выражений [python] - PullRequest
2 голосов
/ 30 августа 2010

Хотелось бы знать, стоит ли избегать регулярных выражений.

На самом деле я в любом случае избегал этого, и некоторые люди давали мне советы, что мне не следует этого избегать, поскольку, если вы знаете, что означает каждая вещь, например:

[] '|' \ A \ B \ d \ D \ W \ w \ S \ Z $ *? ...

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

становится больше нечитаемым, когда становится больше, например: validators.py

email_re = re.compile(
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' #     quoted-string
    r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE)  # domain

Итак, я хотел бы знать причину, чтобы не избегать регулярных выражений?

Ответы [ 6 ]

18 голосов
/ 30 августа 2010

Нет, не избегайте регулярных выражений. Они на самом деле довольно изящный маленький инструмент и сэкономят вам много работы, если вы будете использовать их с умом.

То, чего вы делаете нужно избегать, это пытаться использовать это для всего, недомогание, которое, кажется, поражает новичков в регулярных выражениях, прежде чем они станут немного более вспыльчивыми и немного менее очарованными: 1005 *

Например, не используйте его для проверки адресов электронной почты. Вы можете подтвердить адрес электронной почты, отправив ему электронное письмо со ссылкой, по которой получатель должен нажать, чтобы завершить «транзакцию».

Существуют миллиарды действительных адресов электронной почты (в соответствии с RFC), за которыми нет физического получателя электронной почты. единственный способ убедиться, что получатель получен, - отправить электронное письмо и дождаться подтверждения того, что он был получен и действовал.

Если я нахожу, что пишу регулярное выражение, которое превышает, скажем, 60 символов, я отступаю назад, чтобы увидеть, есть ли более читаемый способ. Точно так же, если я пишу регулярное выражение и возвращаюсь через неделю и не могу сразу узнать, что оно делает, я думаю о его замене. Этот конкретный абзац, конечно, состоит из моих мнений, но они мне хорошо послужили: -)

6 голосов
/ 30 августа 2010

Регулярные выражения - это инструмент. Они идеально подходят для одних задач, а не для других. Как и любой инструмент, используйте их, когда они являются подходящим инструментом для работы. Не избегайте их, потому что кто-то сказал, что они плохие. Узнайте, как их использовать, и тогда вы сможете решать сами, а не зависеть от догмы кого-либо еще.

2 голосов
/ 30 августа 2010

Если вы решите использовать более общий подход к синтаксическому анализу, такой как pyparsing или PLY , вы никогда не будете требовать регулярных выражений (которые могут соответствовать только небольшим подмножество языков, сопоставимых с такими общими синтаксическими анализаторами). Тем не менее, лексеры, такие как в PLY, как правило, построены на регулярных выражениях (которые идеально соответствуют потребностям лексера!), Поэтому вам, вероятно, придется этого избегать (а также мощные инструменты, такие как BeautifulSoup, когда любой «нормальный» пользователь сможет продолжать использовать его и наслаждаться им, просто передавая объект регулярного выражения в качестве селектора, поскольку BeautifulSoup полностью поддерживает это), и ему придется перекодировать множество таких существующих анализаторов с выбранным вами универсальным назначением. разбор пакета.

Производительность может сильно пострадать, конечно, из-за использования чрезвычайно общих инструментов в тех случаях, когда более простые, высокооптимизированные и сжатые будут идеальным решением, а размер вашего кода может «взорваться» до очень большого размера во многих общие случаи. Но если вы не возражаете против того, чтобы программы были в два раза больше и в два раза медленнее и были настроены избегать регулярных выражений любой ценой, вы можете сделать это.

С другой стороны, если ваша основная проблема связана с удобочитаемостью (тоже вполне понятно и заслуживает похвалы), то опция re.VERBOSE, позволяющая широко использовать пробелы и комментарии в шаблоне RE, действительно может творить чудеса. для этой цели без исключения любых преимуществ REs (за исключением разбавления иногда чрезмерной краткости ;-). Вы, конечно, захотите также держать по крайней мере одну систему синтаксического анализа общего назначения под своим поясом, конечно (вместо того, чтобы растягивать RE для выполнения задач, для которых они не подходят, как, к сожалению, делают многие люди!) - но минимальная команда RE хорошо послужит вам во многих случаях (включая, например, полное использование BeautifulSoup и многих других инструментов, которые могут принимать RE в качестве параметров, чтобы применять их соответствующим образом), что, я думаю, вполне рекомендуется.

1 голос
/ 30 августа 2010

Просто для некоторых сравнений, здесь моя версия формата электронной почты проверяется не с помощью регулярного выражения (с тестовыми примерами), а с одним читаемым регулярным выражением, предложенным мне в качестве альтернативы (хотя отправка электронного письма после его принятия - отличная идея):

# -*- coding: utf8 -*- 
import string
print("Valid letters in this computer are: "+string.letters)
import re 
def validateEmail(a): 
    sep=[x for x in a if not (x.isalpha() or 
                              x.isdigit() or 
                              x in r"!#$%&'*+-/=?^_`{|}~]") ] 
    sepjoined=''.join(sep) 
    ## sep joined must be ..@.... form 
    if len(a)>255 or sepjoined.strip('.') != '@': return False 
    end=a 
    for i in sep: 
        part,i,end=end.partition(i) 
        if len(part)<2: return False 
    return len(end)>1 

def emailval(address): 
    pattern = "[\.\w]{2,}[@]\w+[.]\w+" 
    return re.match(pattern, address)

if __name__ == '__main__': 
    emails = [ "test.@web.com","test+john@web.museum", "test+john@web.m", 
               "a@n.dk", "and.bun@webben.de","marjaliisa.hämäläinen@hel.fi", 
               "marja-liisa.hämäläinen@hel.fi", "marjaliisah@hel.",'tony@localhost',
               '1234@23.45','me@somewhere'] 

    print('\n\t'.join(["Valid emails are:"] + 
                      filter(validateEmail,emails)))

    print('\n\t'.join(["Regexp gives wrong answer:"] + 
                       filter(emailval,emails)))

""" Output:
Valid letters in this computer are: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
Valid emails are:
        test+john@web.museum
        and.bun@webben.de
        tony@localhost
        1234@23.45
        me@somewhere
Regexp gives wrong answer:
        test.@web.com
        and.bun@webben.de
        1234@23.45
"""

EDIT: очищена функция фильтра регулярных выражений из этого древнего кода, отредактированного для более разрешающей версии @detly link. Достаточно хорошо для заполнения формы, сначала проверьте меня перед отправкой подтверждения по электронной почте. Окончательно поместите проверку ограничения длины в 255 символов, упомянутую в комментариях.

Этот код по назначению не принимает нормальный a @ b в качестве действительного адреса электронной почты, но принимает меня @ где-то. Другое дело, что это зависит от того, что возвращает isalpha. Таким образом, этот вывод от Ideone.com не принял скандинавское öä, даже если они действительны в настоящее время. При запуске на моем домашнем компьютере они принимаются. Это даже при наличии строки кодирования.

0 голосов
/ 30 августа 2010

(Удалено регулярное выражение, которое якобы было «официальным», но на самом деле не найдено в RFC, из которого, как он утверждал, оно было.)

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

0 голосов
/ 30 августа 2010

Регулярные выражения, вероятно, являются правильным инструментом для извлечения / проверки адресов электронной почты ...

Чтобы извлечь один или несколько адресов электронной почты из необработанного текста:

import re
pat_e = re.compile(r'(?P<email>[\w.+-]+@(?:[\w-]+\.)+[a-zA-Z]{2,})')
emails = []
for r in pat_e.finditer(text):
  emails.append(r.group('email'))
return emails

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

import re
pat_m = re.compile(r'([\w.+-]+@(?:[\w-]+\.)+[a-zA-Z]{2,}$)')
if pat_m.match(text):
  return True
return False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...