Специальные символы

  • . - любой символ, кроме символа новой строки
  • ^ - начало строки
  • $ - конец строки
  • [abc] - любой символ в скобках
  • [^abc] - любой символ, кроме тех, что в скобках
  • a|b - элемент a или b
  • (regex) - выражение рассматривается как один элемент. Кроме того, подстрока, которая совпала с выражением, запоминается

.

Точка обозначает любой символ.

Чаще всего точка используется с символами повторения + и *, чтобы указать, что между определенными выражениями могут находиться любые символы.

Например, с помощью выражения Interface.+Port ID.+ можно описать строку с интерфейсами в выводе sh cdp neighbors detail:

In [1]: cdp = '''
   ...: SW1#show cdp neighbors detail
   ...: -------------------------
   ...: Device ID: SW2
   ...: Entry address(es):
   ...:   IP address: 10.1.1.2
   ...: Platform: cisco WS-C2960-8TC-L,  Capabilities: Switch IGMP
   ...: Interface: GigabitEthernet1/0/16,  Port ID (outgoing port): GigabitEthernet0/1
   ...: Holdtime : 164 sec
   ...: '''

In [2]: re.search(r'Interface.+Port ID.+', cdp).group()
Out[2]: 'Interface: GigabitEthernet1/0/16,  Port ID (outgoing port): GigabitEthernet0/1'

В результат попала только одна строка, так как точка обозначает любой символ, кроме символа перевода строки. Кроме того, символы повторения + и * по умолчанию захватывают максимально длинную строку. Этот аспект рассматривается в подразделе «Жадность символов повторения».

^

Символ ^ означает начало строки. Выражению ^\d+ соответствует подстрока:

In [3]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [4]: re.search(r'^\d+', line).group()
Out[4]: '100'

Символы с начала строки и до решетки (включая решетку):

In [5]: prompt = 'SW1#show cdp neighbors detail'

In [6]: re.search(r'^.+#', prompt).group()
Out[6]: 'SW1#'

$

Символ $ обозначает конец строки.

Выражение \S+$ описывает любые символы, кроме whitespace в конце строки:

In [7]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [8]: re.search(r'\S+$', line).group()
Out[8]: 'FastEthernet0/1'

[]

Символы, которые перечислены в квадратных скобках, означают, что любой из этих символов будет совпадением. Таким образом можно описывать разные регистры:

In [9]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [10]: re.search(r'[Ff]ast', line).group()
Out[10]: 'Fast'

In [11]: re.search(r'[Ff]ast[Ee]thernet', line).group()
Out[11]: 'FastEthernet'

С помощью квадратных скобок можно указать, какие символы могут встречаться на конкретной позиции. Например, выражение ^.+[>#] описывает символы с начала строки и до решетки или знака больше (включая их). С помощью такого выражения можно получить имя устройства:

In [12]: commands = ['SW1#show cdp neighbors detail',
    ...:             'SW1>sh ip int br',
    ...:             'r1-london-core# sh ip route']
    ...:

In [13]: for line in commands:
    ...:     match = re.search(r'^.+[>#]', line)
    ...:     if match:
    ...:         print(match.group())
    ...:
SW1#
SW1>
r1-london-core#

В квадратных скобках можно указывать диапазоны символов. Например, таким образом можно указать, что нас интересует любая цифра от 0 до 9:

In [14]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [15]: re.search(r'[0-9]+', line).group()
Out[15]: '100'

Аналогичным образом можно указать буквы:

In [16]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [17]: re.search(r'[a-z]+', line).group()
Out[17]: 'aa'

In [18]: re.search(r'[A-Z]+', line).group()
Out[18]: 'F'

В квадратных скобках можно указывать несколько диапазонов:

In [19]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [20]: re.search(r'[a-f0-9]+\.[a-f0-9]+\.[a-f0-9]+', line).group()
Out[20]: 'aa12.35fe.a5d3'

Выражение [a-f0-9]+\.[a-f0-9]+\.[a-f0-9]+ описывает три группы символов, разделенных точкой. Символами в каждой группе могут быть буквы a-f или цифры 0-9. Это выражение описывает MAC-адрес.

Еще одна особенность квадратных скобок - специальные символы внутри квадратных скобок теряют свое специальное значение и обозначают просто символ. Например, точка внутри квадратных скобок будет обозначать точку, а не любой символ.

Выражение [a-f0-9]+[./][a-f0-9]+ описывает три группы символов:

  1. буквы a-f или цифры от 0 до 9
  2. точка или слеш
  3. буквы a-f или цифры от 0 до 9

Для строки line совпадением будет такая подстрока:

In [21]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [22]: re.search(r'[a-f0-9]+[./][a-f0-9]+', line).group()
Out[22]: 'aa12.35fe'

Если после открывающейся квадратной скобки указан символ ^, совпадением будет любой символ, кроме указанных в скобках:

In [23]: line = 'FastEthernet0/0    15.0.15.1       YES manual up         up'

In [24]: re.search(r'[^a-zA-Z]+', line).group()
Out[24]: '0/0    15.0.15.1       '

В данном случае выражение описывает все, кроме букв.

|

Вертикальная черта работает как „или“:

In [25]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [26]: re.search(r'Fast|0/1', line).group()
Out[26]: 'Fast'

Обратите внимание на то, как срабатывает | - Fast и 0/1 воспринимаются как целое выражение. То есть, в итоге выражение означает, что мы ищем Fast или 0/1, а не то, что мы ищем Fas, затем t или 0 и 0/1.

()

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

Например, выражение [0-9]([a-f]|[0-9])[0-9] описывает три символа: цифра, потом буква или цифра и цифра:

In [27]: line = "100     aa12.35fe.a5d3    FastEthernet0/1"

In [28]: re.search(r'[0-9]([a-f]|[0-9])[0-9]', line).group()
Out[28]: '100'

Скобки позволяют указывать, какое выражение является одним целым. Это особенно полезно при использовании символов повторения:

In [29]: line = 'FastEthernet0/0    15.0.15.1       YES manual up         up'

In [30]: re.search(r'([0-9]+\.)+[0-9]+', line).group()
Out[30]: '15.0.15.1'

Скобки позволяют не только группировать выражения. Строка, которая совпала с выражением в скобках, запоминается. Ее можно получить отдельно с помощью специальных методов groups и group(n). Это рассматривается в подразделе «Группировка выражений».