содержание
Знакомство с регулярными выражениями Python
Регулярное выражение — это специальная последовательность символов, используемая для определения соответствия строки заданной нами последовательности символов, то есть для проверки соответствия строки определенному шаблону.
Python добавил модуль re начиная с версии 1.5, который предоставляет шаблоны регулярных выражений в стиле Perl. Модуль re обеспечивает полные возможности регулярных выражений для языка Python.
Следующий пример, шаг за шагом, чтобы первоначально понять регулярное выражение.
Например, чтобы определить, содержит ли строка определенный символ или определенные символы, мы обычно используем для этого встроенные функции, как показано ниже:
# 设定一个常量
a = '两点水|twowater|liangdianshui|草根程序员|ReadingWithU'
# 判断是否有 “两点水” 这个字符串,使用 PY 自带函数
print('是否含有“两点水”这个字符串:{0}'.format(a.index('两点水') > -1))
print('是否含有“两点水”这个字符串:{0}'.format('两点水' in a))
Результат выглядит следующим образом:
是否含有“两点水”这个字符串:True
是否含有“两点水”这个字符串:True
Так что, если вы используете регулярные выражения?
Только что упоминалось, что Python предоставляет нам модуль re для реализации всех функций регулярных выражений, поэтому давайте сначала воспользуемся одной из функций:
re.findall(pattern, string[, flags])
Эта функция реализует поиск всех подстрок, соответствующих регулярным выражениям в строке, и формирует возвращаемый список. Конкретные операции заключаются в следующем:
import re
# 设定一个常量
a = '两点水|twowater|liangdianshui|草根程序员|ReadingWithU'
# 正则表达式
findall = re.findall('两点水', a)
print(findall)
if len(findall) > 0:
print('a 含有“两点水”这个字符串')
else:
print('a 不含有“两点水”这个字符串')
Результат вывода:
['两点水']
a 含有“两点水”这个字符串
Как видно из выходных результатов, можно добиться той же функции, что и встроенной функции, но здесь следует подчеркнуть, что приведенный выше пример предназначен только для облегчения нашего понимания регулярных выражений, и написание этого регулярного выражения является бессмысленный. Почему ты так говоришь?
Из-за проблем, которые можно решить с помощью собственных функций Python, нам не нужно использовать регулярные выражения, что излишне. Более того, настройка регулярного выражения в приведенном выше примере стала константой, а не правилом регулярного выражения.Душа регулярного выражения лежит в правилах, так что особого смысла в этом нет.
Так как же написать правила регулярных выражений? Не волнуйтесь, давайте пошагово, начнем с простого, найдем все строчные буквы в строке. Сначала мыfindall
Правила написания регулярных выражений в первом параметре функции, где[a-z]
Он должен соответствовать любой строчной букве, а второму параметру нужно только заполнить строку, которая будет соответствовать. детали следующим образом:
import re
# 设定一个常量
a = '两点水|twowater|liangdianshui|草根程序员|ReadingWithU'
# 选择 a 里面的所有小写英文字母
re_findall = re.findall('[a-z]', a)
print(re_findall)
Результат вывода:
['t', 'w', 'o', 'w', 'a', 't', 'e', 'r', 'l', 'i', 'a', 'n', 'g', 'd', 'i', 'a', 'n', 's', 'h', 'u', 'i', 'e', 'a', 'd', 'i', 'n', 'g', 'i', 't', 'h']
Таким образом мы получаем все строчные буквы в строке.
набор символов
Что ж, благодаря приведенным выше примерам у нас есть предварительное представление о регулярных выражениях Python.Вы можете спросить, каковы правила регулярных выражений и что означают буквы?
На самом деле, они никуда не торопятся, список соответствующих правил регулярных выражений будет приведен далее в этой главе, а эти вещи можно найти с помощью Google в Интернете. Итак, теперь давайте углубимся в наше понимание регулярных выражений и поговорим о наборе символов регулярных выражений.
Набор символов — это набор символов, заключенных в квадратные скобки «[]». Используя набор символов, можно сопоставить один из нескольких символов.
Например, если вы используетеC[ET]O
соответствует CEO или CTO , т.е.[ET]
Представляет E или T . как упоминалось выше[a-z]
, является одной из всех строчных букв, где дефис "-" используется для определения диапазона последовательных символов. Конечно, при таком способе написания он может содержать несколько диапазонов символов, например:[0-9a-fA-F]
, соответствует одной шестнадцатеричной цифре без учета регистра. Обратите внимание, что порядок, в котором определяются символы и диапазоны, не влияет на результат сопоставления.
На самом деле, я так много сказал, я просто хочу доказать, что отношение символов в квадратных скобках "[]" набора символов является отношением ИЛИ. Давайте рассмотрим пример:
import re
a = 'uav,ubv,ucv,uwv,uzv,ucv,uov'
# 字符集
# 取 u 和 v 中间是 a 或 b 或 c 的字符
findall = re.findall('u[abc]v', a)
print(findall)
# 如果是连续的字母,数字可以使用 - 来代替
l = re.findall('u[a-c]v', a)
print(l)
# 取 u 和 v 中间不是 a 或 b 或 c 的字符
re_findall = re.findall('u[^abc]v', a)
print(re_findall)
Результат вывода:
['uav', 'ubv', 'ucv', 'ucv']
['uav', 'ubv', 'ucv', 'ucv']
['uwv', 'uzv', 'uov']
В примере используется инвертированный набор символов, то есть левая квадратная скобка «[», за которой следует угловая скобка «^», будет инвертировать набор символов. Следует иметь в виду, что отрицательный набор символов должен соответствовать символу. Например:q[^u]
не означает: соответствует q, за которым не следует u. Это означает: найдите q, за которым следует символ, отличный от u. Конкретное можно понять, сравнив результаты вывода в приведенном выше примере.
Все мы знаем, что сами регулярные выражения определяют некоторые правила, такие как\d
, соответствует всем числовым символам. Фактически, это эквивалентно [0-9]. Ниже также приведен пример, объясняющий эти специальные символы в виде наборов символов.
import re
a = 'uav_ubv_ucv_uwv_uzv_ucv_uov&123-456-789'
# 概括字符集
# \d 相当于 [0-9] ,匹配所有数字字符
# \D 相当于 [^0-9] , 匹配所有非数字字符
findall1 = re.findall('\d', a)
findall2 = re.findall('[0-9]', a)
findall3 = re.findall('\D', a)
findall4 = re.findall('[^0-9]', a)
print(findall1)
print(findall2)
print(findall3)
print(findall4)
# \w 匹配包括下划线的任何单词字符,等价于 [A-Za-z0-9_]
findall5 = re.findall('\w', a)
findall6 = re.findall('[A-Za-z0-9_]', a)
print(findall5)
print(findall6)
Выходной результат:
['1', '2', '3', '4', '5', '6', '7', '8', '9']
['1', '2', '3', '4', '5', '6', '7', '8', '9']
['u', 'a', 'v', '_', 'u', 'b', 'v', '_', 'u', 'c', 'v', '_', 'u', 'w', 'v', '_', 'u', 'z', 'v', '_', 'u', 'c', 'v', '_', 'u', 'o', 'v', '&', '-', '-']
['u', 'a', 'v', '_', 'u', 'b', 'v', '_', 'u', 'c', 'v', '_', 'u', 'w', 'v', '_', 'u', 'z', 'v', '_', 'u', 'c', 'v', '_', 'u', 'o', 'v', '&', '-', '-']
['u', 'a', 'v', '_', 'u', 'b', 'v', '_', 'u', 'c', 'v', '_', 'u', 'w', 'v', '_', 'u', 'z', 'v', '_', 'u', 'c', 'v', '_', 'u', 'o', 'v', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['u', 'a', 'v', '_', 'u', 'b', 'v', '_', 'u', 'c', 'v', '_', 'u', 'w', 'v', '_', 'u', 'z', 'v', '_', 'u', 'c', 'v', '_', 'u', 'o', 'v', '1', '2', '3', '4', '5', '6', '7', '8', '9']
квантификатор
Приходите, продолжайте углублять свое понимание регулярных выражений.В этой части разберитесь с квантификаторами, зачем использовать квантификаторы, подумайте, если вы хотите сопоставить десятки или сотни символов, вы хотите написать их один за другим, так это появляются квантификаторы.
Словарь квантификаторов: {min,max}. И min, и max являются неотрицательными целыми числами. Если запятая присутствует, а max опущено, max не имеет предела. Если и запятая, и max опущены, повторите min раз. Например,\b[1-9][0-9]{3}\b
, соответствует числам от 1000 до 9999 ("\b" означает границы слов), а\b[1-9][0-9]{2,4}\b
, что соответствует числу от 100 до 99999.
Давайте рассмотрим пример сопоставления английских символов от 4 до 7 букв в строке.
import re
a = 'java*&39android##@@python'
# 数量词
findall = re.findall('[a-z]{4,7}', a)
print(findall)
Выходной результат:
['java', 'android', 'python']
Обратите внимание, что существует различие между жадным и нежадным. Итак, давайте сначала рассмотрим связанные понятия:
Жадный режим: его характеристикой является чтение всей строки за один раз, и, если она не совпадает, она выдает самый правый символ, а затем сопоставляется до тех пор, пока не будет найдена совпадающая строка или длина строки не станет равной 0. Его цель — прочитать как можно больше символов, поэтому он возвращается, как только будет прочитано первое совпадение.
Ленивый режим: его характеристика состоит в том, чтобы начать с левой стороны строки и попытаться сопоставить, не читая символы в строке.Если это не удается, прочитайте еще один символ, а затем сопоставьте и т. д. Когда совпадение найдено , он вернет строку match., а затем снова сопоставит до конца строки.
Приведенный выше пример является жадным.Если вы хотите использовать не жадный, то есть ленивый режим, то как?
Если вы хотите использовать не жадный, добавьте?
, приведенный выше пример изменяется следующим образом:
import re
a = 'java*&39android##@@python'
# 贪婪与非贪婪
re_findall = re.findall('[a-z]{4,7}?', a)
print(re_findall)
Результат выглядит следующим образом:
['java', 'andr', 'pyth']
Как видно из вывода, андроид печатает только кроме andr, а Python печатает только кроме pyth, потому что здесь используется ленивый режим.
Конечно, есть некоторые специальные символы, которые также могут обозначать количества, например:
?
: сообщает движку, что начальный символ должен соответствовать 0 или 1 раз
+
: сообщает движку, что ведущему символу нужно соответствовать 1 или более раз.
*
: сообщает движку, что начальный символ должен соответствовать 0 или более раз
Чтобы обобщить очки знаний этой части, это следующая таблица:
жадность | инерция | описывать |
---|---|---|
? | ? ? | ноль или одно вхождение, эквивалентное {0,1} |
+ | +? | одно или несколько вхождений , эквивалентных {1,} |
* | *? | ноль или более вхождений , что эквивалентно {0,} |
{n} | {п}? | ровно n вхождений |
{n,m} | {н,м}? | Не менее n ветвей с более чем m вхождениями |
{n,} | {н,}? | не менее n вхождений |
Граничные сопоставители и группы
Вышеупомянутые пункты использовались для большого количества места, и теперь мы вводим некоторые концепции символов и групп, соответствующих границам.
Общие средства сопоставления границ следующие:
грамматика | описывать |
---|---|
^ | Совпадение с началом строки (соответствует началу каждой строки в случае нескольких строк) |
$ | Совпадение с концом строки (соответствует концу каждой строки в случае нескольких строк) |
\A | соответствовать только началу строки |
\Z | соответствует только концу строки |
\b | совпадения между \w и \W |
\B | [^\b] |
Группировка, выражение, заключенное в круглые скобки, является группировкой. групповые выражения(...)
На самом деле эта часть символов берется как единое целое.Конечно, групп может быть несколько.Каждый раз, когда группа встречается, число будет увеличиваться на 1, а также после группы могут быть добавлены квантификаторы.
Здесь должен быть пример.Учитывая проблему с местом, я не буду его размещать.
re.sub
В реальном боевом процессе нам часто приходится заменять символы в строке, которые можно использовать в это время.def sub(pattern, repl, string, count=0, flags=0)
Функция re.sub имеет всего пять параметров. Три обязательных параметра: pattern, repl, string; два необязательных параметра: count, flags.
Значения конкретных параметров следующие:
параметр | описывать |
---|---|
pattern | Представляет строку шаблона в обычном |
repl | repl, замена, смысл замененной строки |
string | Это означает, что строка будет обработана и заменена |
count | Для результатов, соответствующих шаблону, count может управлять заменой первых нескольких групп. |
flags | Модификаторы регулярных выражений |
Для конкретного использования можно посмотреть следующий пример.Очень понятно написаны комментарии.Главное отметить,что вторым параметром может передаваться функция,что тоже является силой данного метода.Например,функция в примереconvert
, Оцените символы, переданные для замены, и замените их другими символами.
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
a = 'Python*Android*Java-888'
# 把字符串中的 * 字符替换成 & 字符
sub1 = re.sub('\*', '&', a)
print(sub1)
# 把字符串中的第一个 * 字符替换成 & 字符
sub2 = re.sub('\*', '&', a, 1)
print(sub2)
# 把字符串中的 * 字符替换成 & 字符,把字符 - 换成 |
# 1、先定义一个函数
def convert(value):
group = value.group()
if (group == '*'):
return '&'
elif (group == '-'):
return '|'
# 第二个参数,要替换的字符可以为一个函数
sub3 = re.sub('[\*-]', convert, a)
print(sub3)
Результат вывода:
Python&Android&Java-888
Python&Android*Java-888
Python&Android&Java|888
re.match и re.search
функция повторного сопоставления
грамматика:
re.match(pattern, string, flags=0)
re.match пытается сопоставить шаблон с начала строки, и если совпадение в начале не удалось, match() не возвращает ничего.
функция поиска
грамматика:
re.search(pattern, string, flags=0)
re.search сканирует всю строку и возвращает первое успешное совпадение.
Параметры re.match и re.search в основном одинаковы, а конкретные описания следующие:
параметр | описывать |
---|---|
pattern | соответствие регулярному выражению |
string | строка для соответствия |
flags | Бит флага, используемый для управления методом сопоставления регулярных выражений, например: учитывать ли регистр |
Так в чем же между ними разница?
re.match соответствует только началу строки, если начало строки не соответствует регулярному выражению, сопоставление завершается ошибкой и функция возвращает None, а re.search сопоставляет всю строку до тех пор, пока не будет найдено совпадение. В этом разница между ними.
У re.match и re.search есть много подробных вводных в Интернете, но в личном использовании я все еще предпочитаю использовать re.findall
Взгляните на следующий пример, вы можете сравнить разницу между re.search и re.findall, а также использование нескольких групп. Посмотрите комментарии для деталей и сравните результаты вывода:
Пример:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# 提取图片的地址
import re
a = '<img src="https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg">'
# 使用 re.search
search = re.search('<img src="(.*)">', a)
# group(0) 是一个完整的分组
print(search.group(0))
print(search.group(1))
# 使用 re.findall
findall = re.findall('<img src="(.*)">', a)
print(findall)
# 多个分组的使用(比如我们需要提取 img 字段和图片地址字段)
re_search = re.search('<(.*) src="(.*)">', a)
# 打印 img
print(re_search.group(1))
# 打印图片地址
print(re_search.group(2))
# 打印 img 和图片地址,以元祖的形式
print(re_search.group(1, 2))
# 或者使用 groups
print(re_search.groups())
Результат вывода:
<img src="https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg">
https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg
['https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg']
img
https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg
('img', 'https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg')
('img', 'https://s-media-cache-ak0.pinimg.com/originals/a8/c4/9e/a8c49ef606e0e1f3ee39a7b219b5c05e.jpg')
Наконец, регулярные выражения — это очень мощные инструменты, которые часто можно использовать для решения проблем, которые не могут решить встроенные функции работы со строками, а регулярные выражения доступны в большинстве языков. Python имеет множество применений, но регулярные выражения неотделимы от модулей сканирования и анализа данных. Так что регулярные выражения очень важны для изучения Python. Наконец, некоторые часто используемые регулярные выражения и регулярные выражения, а также метасимволы регулярных выражений и документы по синтаксису, поддерживаемые Python, прилагаются.
github: https://github.com/TwoWater/Python/blob/master/python14/%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99 %E8%A1%A8%E8%BE%BE%E5%BC%8F.md
Добро пожаловать всем, чтобы начать, https://github.com/TwoWater/Python, это библиотека для массовых блогов серии Python. Вы также можете подписаться на мой публичный аккаунт в WeChat: