概念として、正規表現は Python に固有のものではありません。ただし、Python での正規表現の実際の使用には、まだいくつかの小さな違いがあります。
この記事は、Python 正規表現に関する一連の記事の一部です。このシリーズの最初の記事では、Python で正規表現を使用する方法に焦点を当て、Python のユニークな機能のいくつかを取り上げます。
Pythonで文字列を検索・見つける方法をいくつか紹介します。次に、グループ化を使用して、見つかった一致するオブジェクトのサブ項目を処理する方法について説明します。
私たちが使用したい Python の正規表現のモジュールは、通常「re」と呼ばれます。
>>> import re
1. Python のプリミティブ型文字列
Python コンパイラーは、文字列定数内のエスケープ文字を表すために '' (バックスラッシュ) を使用します。
バックスラッシュの後にコンパイラによって認識される特殊文字の文字列が続く場合、エスケープ シーケンス全体が対応する特殊文字に置き換えられます (たとえば、「n」はコンパイラによって改行文字に置き換えられます)。
しかし、これは Python で正規表現を使用する場合に問題を引き起こします。バックスラッシュは、正規表現内の特殊文字 (* や + など) をエスケープするために 're' モジュールでも使用されるためです。
この 2 つの混合物は、エスケープ文字自体をエスケープする必要がある場合 (特殊文字が Python と正規表現コンパイラーの両方で認識される場合) と、エスケープする必要がない場合があります (特殊文字のみが認識される場合) ことを意味します。 Python コンパイラによって認識されます)。
必要なバックスラッシュの数を計算する代わりに、生の文字列を使用できます。
プリミティブ型の文字列は、通常の文字列の二重引用符の前に「r」文字を追加するだけで作成できます。文字列がプリミティブ型の場合、Python コンパイラは置換を試みません。本質的には、文字列にまったく干渉しないようにコンパイラに指示していることになります。
>>> string = 'This is a\nnormal string' >>> rawString = r'and this is a\nraw string' >>> print string
これは通常の文字列です
>>> print rawString and this is a\nraw string
これはプリミティブ型の文字列です。
Python で正規表現を使用した検索
「re」モジュールは、入力文字列に対して正確なクエリを実行するためのメソッドをいくつか提供します。ここで説明するメソッドは次のとおりです:
•re.match() •re.search() •re.findall()
各メソッドは、正規表現と一致する文字列を受け取ります。これらの各メソッドがどのように機能し、どのように異なるのかを理解するために、それぞれのメソッドを詳しく見てみましょう。
2. re.match を使用して検索 – マッチングが始まります
まず match() メソッドを見てみましょう。 match() メソッドの仕組みは、検索対象の文字列の先頭がパターンと一致する場合にのみ一致を見つけるというものです。
たとえば、文字列「dog cat Dog」に対して math() メソッドを呼び出すと、検索パターン「dog」が一致します:
>>> re.match(r'dog', 'dog cat dog') <_sre.SRE_Match object at 0xb743e720< >>> match = re.match(r'dog', 'dog cat dog') >>> match.group(0) 'dog'
group() メソッドについては後ほど説明します。現時点では、引数として 0 を指定して呼び出したこと、および group() メソッドが見つかった一致するパターンを返すことだけを知っておく必要があります。
返された SRE_Match オブジェクトも今のところスキップしました。これについてはすぐに説明します。
ただし、同じ文字列で math() メソッドを呼び出し、パターン 'cat' を探しても、一致するものは見つかりません。
>>> re.match(r'cat', 'dog cat dog') >>>
3. re.search を使用して検索します – 任意の位置に一致します
search() メソッドは match() に似ていますが、search() メソッドは先頭からの一致のみを検索することに限定されません。文字列の例では、文字列の例で 'cat' を検索すると、一致する文字列が見つかります:
search(r'cat', 'dog cat dog') >>> match.group(0) 'cat'
ただし、search() メソッドは一致が見つかった後に停止するため、文字列の例では The searc を使用します。 () メソッドは、最初の出現時にのみ「dog」を検索します。
>>> match = re.search(r'dog', 'dog cat dog') >>> match.group(0) 'dog'
4. re.findall を使用する - 一致するすべてのオブジェクト
これまで Python で最もよく使用した find メソッドは findall() メソッドです。 findall() メソッドを呼び出すと、一致オブジェクトを取得する代わりに、一致するすべてのパターンのリストを非常に簡単に取得できます (一致オブジェクトについては次に説明します)。私にとってはもっとシンプルです。サンプル文字列に対して findall() メソッドを呼び出すと次の結果が得られます:
['dog', 'dog'] >>> re.findall(r'cat', 'dog cat dog') ['cat']
5. match.start メソッドと match.end メソッドを使用する
その後、以前に返された search() メソッドと match() メソッドが返されます。 「オブジェクト」とは正確には何ですか?
単に文字列の一致する部分を返すのとは異なり、search() と match() によって返される「一致するオブジェクト」は、実際には部分文字列を一致させるためのラッパー クラスです
。 group() メソッドを呼び出すことで一致する部分文字列を取得できることがわかりましたが (次のセクションで説明するように、一致オブジェクトはグループ化の問題を扱うときに実際に非常に役立ちます)、一致オブジェクトには一致に関する詳細も含まれています。部分文字列情報:
たとえば、一致オブジェクトは、元の文字列のどこで一致するコンテンツが開始され、どこで終了するかを知ることができます。
就像我之前提到的,匹配对象在处理分组时非常得心应手。
分组是对整个正则表达式的特定子串进行定位的能力。我们可以定义一个分组做为整个正则表达式的一部分,然后单独的对这部分对应匹配到的内容定位。
让我们来看一下它是怎么工作的:
>>> contactInfo = 'Doe, John: 555-1212'
我刚才创建的字符串类似一个从某人的地址本里取出来的一个片段。我们可以通过这样一个正则表达式来匹配这一行:
>>> re.search(r'\w+, \w+: \S+', contactInfo) <_sre.SRE_Match object at 0xb74e1ad8<
通过用圆括号来(字符‘('和‘)')包围正则表达式的特定部分,我们可以对内容进行分组然后对这些子组做单独处理。
>>> match = re.search(r'(\w+), (\w+): (\S+)', contactInfo)
这些分组可以通过用分组对象的group()方法得到。它们可以通过其在正则表达式中从左到右出现的数字顺序来定位(从1开始):
>>> match.group(1) 'Doe' >>> match.group(2) 'John' >>> match.group(3) '555-1212'
组的序数从1开始的原因是因为第0个组被预留来存放所有匹配对象(我们在之前学习match()方法和search()方法到时候看到过)。
>>> match.group(0) 'Doe, John: 555-1212'
7. 使用 match.group 通过别名来分组
有时候,特别是当一个正则表达式有很多分组的时候,通过组的出现次序来定位就会变的不现实。Python还允许你通过下面的语句来指定一个组名:
>>> match = re.search(r'(?P<last>\w+), (?P<first>\w+): (?P<phone>\S+)', contactInfo)
我们还是可以用group()方法获取分组的内容,但这时候我们要用我们所指定的组名而不是之前所使用的组的所在位数。
>>> match.group('last') 'Doe' >>> match.group('first') 'John' >>> match.group('phone') '555-1212'
这大大加强了代码的明确性和可读性。你可以想像当正则表达式变得越来越复杂,去弄懂一个分组到捕获了什么内容将会变得越来越困难。给你的分组命名将明确的告诉了你和你的读者你的意图。
尽管findall()方法不返回分组对象,它也可以使用分组。类似的,findall()方法将返回一个元组的集合,其中每个元组中的第N个元素对应了正则表达式中的第N个分组。
>>> re.findall(r'(\w+), (\w+): (\S+)', contactInfo) [('Doe', 'John', '555-1212')]
但是,给分组命名并不适用于findall()方法。
在本文中我们介绍了Python中使用正则表达式的一些基础。我们学习了原始字符串类型(还有它能帮你解决的在使用正则表达式中一些头痛的问题)。我们还学习了如何适使用match(), search(), and findall()方法进行基本的查询,以及如何使用分组来处理匹配对象的子组件。
和往常一样,如果想查看更多关于这个主题的内容,re模块的Python官方文档是一个非常好的资源。
在以后的文章中,我们将更深入的讨论Python中正则表达式的应用。我们将更加全面的学习匹配对象,学习如何使用它们在字符串中做替换,甚至使用它们从文本文件中去解析Python数据结构。