Skip to content

re#

メソッド#

  • match 文字列の先頭で正規表現パターンにマッチした場合、対応するマッチオブジェクトを返す。
  • search 文字列を走査し、正規表現パターンがマッチする最初の場所を探し、対応するマッチオブジェクトを返します。
  • findall テンプレートとのすべての一致を検索します。結果の文字列をリストとして返す。
  • finditer テンプレートと一致するものを検索し、イテレータを返す。
  • compile 正規表現をコンパイルします。
  • fullmatch 文字列全体が正規表現パターンにマッチする場合、対応するマッチオブジェクトを返す。
  • sub 正規表現にマッチした文字列を置換する。
  • split 正規表現にマッチした箇所で文字列を分割する。

Info

正規表現にマッチしなかった場合はNoneをかえします。

基本的なマッチ例#

import re

log = "RP/0/0/CPU0:Apr 22 15:49:42.020 JST: mpls_ldp[1181]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 2.2.2.2:0 is UP (IPv4 connection)" 
match = re.search(r'Neighbor (\d+.\d+.\d+.\d+)', log)

print(match)
# マッチオブジェクトを返す。
# <re.Match object; span=(109, 125), match='Neighbor 2.2.2.2'>

print(match.group())
# 文字列は.group()で取得
# Neighbor 2.2.2.2

# グループ0を指定しても同じ結果を返す
print(match.group(0))

# 他の番号は、関連するグループの内容を返す
print(match.group(1))

# 既存のグループの数よりも大きいグループ番号で `group` メソッドを呼び出すと、IndexError
# print(match.group(2))

# 複数のグループ番号を持つメソッドを呼び出すと、結果は一致に対応する文字列を持つタプル
print(match.group(0,1))
# ('Neighbor 2.2.2.2', '2.2.2.2')

groupdict()#

正規表現で(?P<key>pattern)を用いて、マッチしたオブジェクトには groupdict()メソッドで辞書を取得できます。

import re

config = """
router static address-family ipv4 unicast 1.1.1.1/32 TenGigE0/0/0/0 1.1.1.2 bfd fast-detect minimum-interval 500 multiplier 3
router static address-family ipv6 unicast 1:1:1:1::2/128 TenGigE0/0/0/0 10:10:10:10::1 bfd fast-detect minimum-interval 500 multiplier 3
"""

static_match = re.search(
    r'router static address-family ipv(4|6) unicast '
    r'(?P<dst_address>\S+) '
    r'(?P<interface>\S+) '
    r'(?P<next_hop>\S+) '
    r'bfd fast-detect minimum-interval '
    r'(?P<bfd_interval>\d+) multiplier '
    r'(?P<bfd_multiplier>\d+)'
    ,config)

print(static_match.groupdict())

re.compile#

複数行に分けて正規表現を記述する例1

static_match = re.compile(
    r'router static address-family ipv(4|6) unicast '
    r'(?P<dst_address>\S+) '
    r'(?P<interface>\S+) '
    r'(?P<next_hop>\S+) '
    r'bfd fast-detect minimum-interval '
    r'(?P<bfd_interval>\d+) multiplier '
    r'(?P<bfd_multiplier>\d+)'
    )

複数行に分けて正規表現を記述する例2

static_pattern = re.compile(
    r'''^router\sstatic\saddress-family\sipv6\sunicast\s
    # コメントアウトを書けます。
    (?P<dst_address>\S+)\s
    (?P<interface>\S+)\s
    (?P<next_hop>\S+)
    bfd\sfast-detect\sminimum-interval\s
    (?P<bfd_interval>\d+)\s
    (?P<bfd_multiplier>\d+)
  ''',re.X)

Tip

複数行記述する場例2は三連引用符(トリプルクオーテーション)と、オプション re.X を使用します。 re.X では空白、コメントアウトは無視されます。正規表現で空白がある場合は\sにて記述します。

Quote

re.compile() やモジュールレベルのマッチング関数に渡された最新のパターンはコンパイル済みのものがキャッシュされるので、 一度に正規表現を少ししか使わな

show cdp neighbor の処理例#

for 文で読み込んだテキストを一行ずつ処理。 startswithを条件分岐に用いている

import re
from pprint import pprint

def parse_cdp(filename):
    result = {}

    with open(filename) as f:
        for line in f:
            # startswith を使用して処理
            if line.startswith('Device ID'):
                neighbor = re.search('Device ID: (\S+)', line).group(1)
                result[neighbor] = {}
            elif line.startswith('  IP address'):
                ip = re.search('IP address: (\S+)', line).group(1)
                result[neighbor]['ip'] = ip
            elif line.startswith('Platform'):
                platform = re.search('Platform: (\S+ \S+),', line).group(1)
                result[neighbor]['platform'] = platform
            elif line.startswith('Cisco IOS Software'):
                ios = re.search('Cisco IOS Software, (.+), RELEASE',
                                line).group(1)
                result[neighbor]['ios'] = ios

    return result


pprint(parse_cdp('sh_cdp_neighbors_sw1.txt'))