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

Существование метасимволов несколько усложняет создание регулярных выражений, состоящих из обычных символов, являющихся также метасимволами, например, $. В таких случаях метасимволы необходимо экранировать, ставя перед ними обратную косую черту.
Хотя такой способ также может создать проблемы, так как обратные косые черты также имеют функцию экранирования в коде Python. По этой причине может потребоваться три или четыре бэкслэша в строке.

Первый метасимвол, с которым мы познакомимся – . (точка).
Точка означает любой символ, исключая символ новой строки.

import re

pattern = r"gr.y"

if re.match(pattern, "grey"):
    print("Match 1")

if re.match(pattern, "gray"):
    print("Match 2")

if re.match(pattern, "blue"):
    print("Match 3")

Далее рассмотрим метасимволы ^ и $.
Они указывают соответственно на начало и конец строки.

import re

pattern = r"^gr.y$"

if re.match(pattern, "grey"):
    print("Match 1")

if re.match(pattern, "gray"):
    print("Match 2")

if re.match(pattern, "stingray"):
    print("Match 3")

Классы символов предназначены для поиска конкретного символа из набора символов.
Класс символов создается путем заключения искомых символов в квадратные скобки.

import re

pattern = r"[aeiou]"

if re.search(pattern, "grey"):
    print("Match 1")

if re.search(pattern, "qwertyuiop"):
    print("Match 2")

if re.search(pattern, "rhythm myths"):
    print("Match 3")

Классы символов могут также использоваться для поиска символов в заданном диапазоне.
Вот несколько примеров:
класс [a-z] – поиск любой строчной буквы
класс [G-P] – поиск любого символа верхнего регистра от G до P
класс [0-9] – поиск любой цифры.
Класс может состоять из больше, чем одного диапазона. Например, класс [A-Za-z] означает поиск любой буквы алфавита верхнего или нижнего регистра.

import re

pattern = r"[A-Z][A-Z][0-9]"

if re.search(pattern, "LS8"):
    print("Match 1")

if re.search(pattern, "E3"):
    print("Match 2")

if re.search(pattern, "1ab"):
    print("Match 3")

Чтобы инвертировать класс символов, нужно поместить ^ в начало определения класса.
Это команда ищет любой символ, кроме символов класса.
Другие метасимволы, такие как $ и . не имеют никакого специального значения в классах символов.
Метасимвол ^ не имеет специального значения, если он не является первым символом класса.

import re

pattern = r"[^A-Z]"

if re.search(pattern, "this is all quiet"):
    print("Match 1")

if re.search(pattern, "AbCdEfG123"):
    print("Match 2")

if re.search(pattern, "THISISALLSHOUTING"):
    print("Match 3")

Среди других метасимволов: *, +, ?, { и }.
С их помощью задается число упоминаний.
Метасимвол * означает «ноль или более упоминаний объекта поиска». Это команда найти как можно больше упоминаний. «Объект поиска» указывается в скобках; им может быть один символ, класс или группа символов.

import re

pattern = r"egg(spam)*"

if re.match(pattern, "egg"):
    print("Match 1")

if re.match(pattern, "eggspamspamegg"):
    print("Match 2")

if re.match(pattern, "spam"):
    print("Match 3")

Метасимвол + очень похож на * с тем отличием, что он означает «одно (или более) упоминание», в отличие от «ноль или более упоминаний».

import re

pattern = r"g+"

if re.match(pattern, "g"):
    print("Match 1")

if re.match(pattern, "gggggggggggggg"):
    print("Match 2")

if re.match(pattern, "abc"):
    print("Match 3")

Метасимвол ? означает «ноль повторений или одно повторение».

import re

pattern = r"ice(-)?cream"

if re.match(pattern, "ice-cream"):
    print("Match 1")

if re.match(pattern, "icecream"):
    print("Match 2")

if re.match(pattern, "sausages"):
    print("Match 3")

if re.match(pattern, "ice--ice"):
    print("Match 4")

Фигурные скобки можно использовать для поиска числа упоминаний между двумя числами.
Выражение {х, у} означает «упоминания объекта поиска между х и у».
Следовательно, {0,1} – то же самое, что ?.
Если первое число отсутствует, программа считает, что это число ноль. Если второе число отсутствует, программа будет искать до бесконечности.

import re

pattern = r"9{1,3}$"

if re.match(pattern, "9"):
    print("Match 1")

if re.match(pattern, "999"):
    print("Match 2")

if re.match(pattern, "9999"):
    print("Match 3")