Python 2.6+ str.format() и регулярные выражения
Использование str.format()
- это новый стандарт форматирования строк в Python 2.6 и Python 3. У меня возникла проблема при использовании str.format()
с регулярными выражениями.
Я написал регулярное выражение, чтобы вернуть все домены, которые находятся на одном уровне ниже указанного домена или любых доменов, которые на 2 уровня ниже указанного домена, если 2-й уровень ниже www...
Предполагая, что указанным доменом является delivery.com, мое регулярное выражение должно возвращать a.delivery.com, b.delivery.com, www.c.delivery.com... но он не должен возвращать xadelivery.com.
import re
str1 = "www.pizza.delivery.com"
str2 = "w.pizza.delivery.com"
str3 = "pizza.delivery.com"
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str1): print 'String 1 matches!'
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str2): print 'String 2 matches!'
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str3): print 'String 3 matches!'
Запуск этого должен дать результат:
String 1 matches!
String 3 matches!
Теперь проблема заключается в том, что я пытаюсь заменить delivery.com динамически с помощью str.format...
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}{domainName}$'.format(domainName = 'delivery.com'), str1): print 'String 1 matches!'
Кажется, что это сбой, потому что str.format()
ожидает, что параметры {3}
и {1}
будут функциями. (Я предполагаю)
Я мог бы конкатенировать строку с помощью оператора +
'^(w{3}\.)?([0-9A-Za-z-]+\.){1}' + domainName + '$'
Вопрос сводится к тому, можно ли использовать str.format()
, когда строка (обычно регулярное выражение) имеет в ней < {n}?
Ответы
Ответ 1
вам сначала нужно форматировать строку, а затем использовать регулярное выражение. Это действительно не стоит ставить все в одну линию. Экранирование выполняется путем удвоения фигурных скобок:
>>> pat= '^(w{{3}}\.)?([0-9A-Za-z-]+\.){{1}}{domainName}$'.format(domainName = 'delivery.com')
>>> pat
'^(w{3}\\.)?([0-9A-Za-z-]+\\.){1}delivery.com$'
>>> re.match(pat, str1)
Кроме того, re.match
соответствует в начале строки, вам не нужно ставить ^
, если вы используете re.match
, вам нужно ^
, если вы используете re.search
.
Обратите внимание, что {1}
в regex довольно избыточно.
Ответ 2
Per документация, если вам нужен литерал {
или }
, чтобы выжить в операции форматирования, используйте {{
и }}
в исходной строке.
'^(w{{3}}\.)?([0-9A-Za-z-]+\.){{1}}{domainName}$'.format(domainName = 'delivery.com')