Соответствие началу строки
Первый аргумент re.match()
является регулярным выражением, вторая строка , чтобы соответствовать:
import re
pattern = r"123"
string = "123zzb"
re.match(pattern, string)
# Out: <_sre.SRE_Match object; span=(0, 3), match='123'>
match = re.match(pattern, string)
match.group()
# Out: '123'
Можно заметить , что переменная шаблона представляет собой строку с префиксом r
, что указывает на то, что строка является исходным строка символов.
Сырые строковый литерал имеет несколько иного синтаксис , чем строка буквального, а именно обратный слэш \
в сыре строковых литералов означает «только обратной косой черты» , и нет никакой необходимости удвоения люфтов , чтобы избежать «экранирующих последовательностей» , такие как символ новой строки ( \n
) , вкладки ( \t
), забой ( \
), формы-каналы ( \r
), и так далее. В обычных строковых литералах каждый обратный слеш должен быть удвоен, чтобы его не принимали за начало escape-последовательности.
Следовательно, r"\n"
является строкой из 2 -х символов: \
и n
.Regex модель также использовать обратную косую черту, например , \d
относится к любому цифровому символу. Мы можем избежать того , чтобы удвоить наши избежать строки ( "\\d"
) с использованием сырьевых строк ( r"\d"
).
Например:
string = "\\t123zzb" # here the backslash is escaped, so there's no tab, just '\' and 't'
pattern = "\\t123" # this will match \t (escaping the backslash) followed by 123
re.match(pattern, string).group() # no match
re.match(pattern, "\t123zzb").group() # matches '\t123'
pattern = r"\\t123"
re.match(pattern, string).group() # matches '\\t123'
Сопоставление выполняется только с начала строки. Если вы хотите , чтобы соответствовать в любом месте использовать re.search
вместо:
match = re.match(r"(123)", "a123zzb")
match is None
# Out: True
match = re.search(r"(123)", "a123zzb")
match.group()
# Out: '123'
поиск
pattern = r"(your base)"
sentence = "All your base are belong to us."
match = re.search(pattern, sentence)
match.group(1)
# Out: 'your base'
match = re.search(r"(belong.*)", sentence)
match.group(1)
# Out: 'belong to us.'
Поиск осуществляется в любом месте строки , в отличие от re.match
.Вы можете также использовать re.findall
.
Вы можете также искать в начале строки (используйте ^
),
match = re.search(r"^123", "123zzb")
match.group(0)
# Out: '123'
match = re.search(r"^123", "a123zzb")
match is None
# Out: True
в конце строки (используйте $
),
match = re.search(r"123$", "zzb123")
match.group(0)
# Out: '123'
match = re.search(r"123$", "123zzb")
match is None
# Out: True
или оба (использовать оба ^
и $
):
match = re.search(r"^123$", "123")
match.group(0)
# Out: '123'
группирование
Группировка осуществляется с помощью скобок. Вызов group()
возвращает строку , образованную из согласующих скобок подгрупп.
match.group() # Group without argument returns the entire match found
# Out: '123'
match.group(0) # Specifying 0 gives the same result as specifying no argument
# Out: '123'
Аргументы могут также быть предоставлена group()
для извлечения конкретной подгруппы.
Из документации :
Если есть единственный аргумент, результат - единственная строка; если имеется несколько аргументов, результатом является кортеж с одним элементом на аргумент.
Вызов groups()
, с другой стороны, возвращает список кортежей , содержащих подгруппу.
sentence = "This is a phone number 672-123-456-9910"
pattern = r".*(phone).*?([\d-]+)"
match = re.match(pattern, sentence)
match.groups() # The entire match as a list of tuples of the paranthesized subgroups
# Out:('phone', '672-123-456-9910')
m.group() # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'
m.group(0) # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'
m.group(1) # The first parenthesized subgroup.
# Out: 'phone'
m.group(2) # The second parenthesized subgroup.
# Out: '672-123-456-9910'
m.group(1, 2) # Multiple arguments give us a tuple.
# Out:('phone', '672-123-456-9910')
Именованные группы
match = re.search(r'My name is (?P<name>[A-Za-z ]+)', 'My name is John Smith')
match.group('name')
# Out: 'John Smith'
match.group(1)
# Out: 'John Smith'
Создает группу захвата, на которую можно ссылаться как по имени, так и по индексу.
Не захватывающие группы
Используя (?:)
создает группу, но группа не улавливается. Это означает, что вы можете использовать его как группу, но это не будет загрязнять ваше «групповое пространство».
re.match(r'(\d+)(\+(\d+))?', '11+22').groups()
# Out:('11', '+22', '22')
re.match(r'(\d+)(?:\+(\d+))?', '11+22').groups()
# Out:('11', '22')
Этот пример соответствует 11+22
или 11
, но не 11+
.Это так +
знак и второй член сгруппированы. С другой стороны, +
знак не улавливается.
Экранирование специальных персонажей
Специальные символы (например , класса символов скобки [
и ]
ниже) не соответствуют буквально:
match = re.search(r'[b]', 'a[b]c')
match.group()
# Out: 'b'
Избегая специальных символов, они могут быть сопоставлены буквально:
match = re.search(r'\[b\]', 'a[b]c')
match.group()
# Out: '[b]'
re.escape()
функция может использоваться , чтобы сделать это для вас:
re.escape('a[b]c')
# Out: 'a\\[b\\]c'
match = re.search(re.escape('a[b]c'), 'a[b]c')
match.group()
# Out: 'a[b]c'
re.escape()
функция экранирует все специальные символы, так что это полезно , если вы составляете регулярное выражение на основе пользовательского ввода:
username = 'A.C.' # suppose this came from the user
re.findall(r'Hi {}!'.format(username), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!', 'Hi ABCD!']
re.findall(r'Hi {}!'.format(re.escape(username)), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!']
Замена
Замены могут быть сделаны на строки , используя re.sub
.
Замена строк
re.sub(r"t[0-9][0-9]", "foo", "my name t13 is t44 what t99 ever t44")
# Out: 'my name foo is foo what foo ever foo'
Использование групповых ссылок
Замены с небольшим количеством групп можно сделать следующим образом:
re.sub(r"t([0-9])([0-9])", r"t\2\1", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'
Тем не менее, если вы сделаете идентификатор группы , как «10», это не работает : \10
читаются как «идентификационный номер 1 с последующим 0». Таким образом , вы должны быть более конкретными и использовать \g<i>
обозначения:
re.sub(r"t([0-9])([0-9])", r"t\g<2>\g<1>", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'
Использование функции замены
items = ["zero", "one", "two"]
re.sub(r"a\[([0-3])\]", lambda match: items[int(match.group(1))], "Items: a[0], a[1], something, a[2]")
# Out: 'Items: zero, one, something, two'
Найти все неперекрывающиеся совпадения
re.findall(r"[0-9]{2,3}", "some 1 text 12 is 945 here 4445588899")
# Out: ['12', '945', '444', '558', '889']
Обратите внимание , что r
перед тем "[0-9]{2,3}"
говорит Python интерпретировать строку как есть; как «сырая» строка.
Вы можете также использовать re.finditer()
, которая работает точно так же , как re.findall()
, но возвращает итератор с SRE_Match
объектов вместо списка строк:
results = re.finditer(r"([0-9]{2,3})", "some 1 text 12 is 945 here 4445588899")
print(results)
# Out: <callable-iterator object at 0x105245890>
for result in results:
print(result.group(0))
''' Out:
12
945
444
558
889
'''
Предварительно скомпилированные шаблоны
import re
precompiled_pattern = re.compile(r"(\d+)")
matches = precompiled_pattern.search("The answer is 41!")
matches.group(1)
# Out: 41
matches = precompiled_pattern.search("Or was it 42?")
matches.group(1)
# Out: 42
Компиляция шаблона позволяет использовать его позже в программе. Тем не менее, обратите внимание , что Python кэширует недавно использованные выражения ( документы , SO ответить ), поэтому «программы , которые используют только несколько регулярных выражений в то время , не нужно беспокоиться о составлении регулярных выражений».
import re
precompiled_pattern = re.compile(r"(.*\d+)")
matches = precompiled_pattern.match("The answer is 41!")
print(matches.group(1))
# Out: The answer is 41
matches = precompiled_pattern.match("Or was it 42?")
print(matches.group(1))
# Out: Or was it 42
Может использоваться с re.match ().
Проверка на допустимые символы
Если вы хотите проверить, что строка содержит только определенный набор символов, в этом случае az, AZ и 0-9, вы можете сделать это следующим образом:
import re
def is_allowed(string):
characherRegex = re.compile(r'[^a-zA-Z0-9.]')
string = characherRegex.search(string)
return not bool(string)
print(is_allowed("abyzABYZ0099"))
# Out: 'True'
print(is_allowed("#*@#$%^"))
# Out: 'False'
Вы также можете адаптировать выражение линию из [^a-zA-Z0-9.]
На [^a-z0-9.]
, Чтобы запретить прописные буквы, например.
Частичный кредит: https://codecamp.ru/a/1325265/2697955
Разделение строки с помощью регулярных выражений
Вы также можете использовать регулярные выражения, чтобы разбить строку. Например,
import re
data = re.split(r'\s+', 'James 94 Samantha 417 Scarlett 74')
print( data )
# Output: ['James', '94', 'Samantha', '417', 'Scarlett', '74']
Флаги
В некоторых особых случаях нам нужно изменить поведение регулярного выражения, это делается с помощью флагов. Флаги могут быть установлены двумя способами, через flags
ключевого слова или непосредственно в выражении.
Ключевое слово флаги
Ниже приведен пример для re.search
, но это работает для большинства функций в re
модуле.
m = re.search("b", "ABC")
m is None
# Out: True
m = re.search("b", "ABC", flags=re.IGNORECASE)
m.group()
# Out: 'B'
m = re.search("a.b", "A\nBC", flags=re.IGNORECASE)
m is None
# Out: True
m = re.search("a.b", "A\nBC", flags=re.IGNORECASE|re.DOTALL)
m.group()
# Out: 'A\nB'
Общие флаги
Флаг Краткое описание re.IGNORECASE
, re.I
Заставляет шаблон игнорировать случай re.DOTALL
, re.S
Делает .
сопоставить все, включая переводы строк re.MULTILINE
, re.M
Делает ^
соответствовать началу строки и $
конца строки re.DEBUG
Включает отладочную информацию
Для полного списка всех доступных флагов проверить документы
Встроенные флаги
Из документации :
(?iLmsux)
(один или более букв из набора 'I', 'L', 'м', 'S', 'и', 'х'.)
Группа соответствует пустой строке; буквы устанавливают соответствующие флаги: re.I (игнорировать регистр), re.L (зависит от локали), re.M (многострочный), re.S (точка соответствует всем), re.U (зависит от Unicode) и re.X (многословный), для всего регулярного выражения. Это полезно, если вы хотите включить флаги как часть регулярного выражения вместо передачи аргумента флага в функцию re.compile ().
Обратите внимание, что флаг (? X) изменяет способ анализа выражения. Его следует использовать сначала в строке выражения или после одного или нескольких пробельных символов. Если перед флагом есть непробельные символы, результаты не определены.
Перебор совпадений с использованием `re.finditer`
Вы можете использовать re.finditer
перебрать все матчи в строке. Это дает вам (по сравнению с re.findall
дополнительной информации, например, информации о местоположении матча в строке (индексы):
import re
text = 'You can try to find an ant in this string'
pattern = 'an?\w' # find 'an' either with or without a following word character
for match in re.finditer(pattern, text):
# Start index of match (integer)
sStart = match.start()
# Final index of match (integer)
sEnd = match.end()
# Complete match (string)
sGroup = match.group()
# Print match
print('Match "{}" found at: [{},{}]'.format(sGroup, sStart,sEnd))
Результат:
Match "an" found at: [5,7]
Match "an" found at: [20,22]
Match "ant" found at: [23,26]
Соответствовать выражению только в определенных местах
Часто вы хотите , чтобы соответствовать выражение только в определенных местах (оставляя их нетронутыми в других, то есть). Рассмотрим следующее предложение:
An apple a day keeps the doctor away (I eat an apple everyday).
Здесь «яблоко» встречается дважды , которые могут быть решены с помощью так называемым отслеживанием источников глаголов управления , которые поддерживаются в новом regex
модуля. Идея заключается в следующем:
forget_this | or this | and this as well | (but keep this)
На нашем примере с яблоком это будет:
import regex as re
string = "An apple a day keeps the doctor away (I eat an apple everyday)."
rx = re.compile(r'''
\([^()]*\) (*SKIP)(*FAIL) # match anything in parentheses and "throw it away"
| # or
apple # match an apple
''', re.VERBOSE)
apples = rx.findall(string)
print(apples)
# only one
Это соответствует «яблоку» только тогда, когда его можно найти за скобками.
Вот как это работает:
- Глядя слева направо, регулярное выражение двигатель потребляет все , чтобы слева,
(*SKIP)
действует как «всегда-истинным самоутверждения». После этого, он правильно не работает на(*FAIL)
и откатывается. - Теперь он попадает в точку
(*SKIP)
справа налево (он же в то время как возвратов) , где запрещено идти дальше влево. Вместо этого, двигатель сказал , чтобы выбросить что - нибудь налево и перейти к точке , где(*SKIP)
был вызван.