Python - 複数行のテキスト ブロックに一致する正規表現

Salman Mehmood 2023年10月8日
  1. 複数行の文字列に一致する正規表現を記述する理由
  2. 複数行の文字列を一致させるために考えられる解決策
Python - 複数行のテキスト ブロックに一致する正規表現

この記事では、複数行の文字列で特定のパターンを検索する方法について説明します。 このソリューションでは、既知および未知のパターンに対するいくつかのアプローチを妥協し、一致するパターンがどのように機能するかを説明します。

複数行の文字列に一致する正規表現を記述する理由

次のテキスト ブロックがあるとします。

Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.\n
\n
IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.

上記のテキスト ブロックから、開始テキストを見つける必要があり、テキストは数行下に表示されます。 \n は改行を表し、リテラル テキストではないことに注意してください。

要約すると、複数の行にまたがるテキストを検索して照合し、テキストの間に入る可能性のある空の行を無視します。 上記のテキストの場合、単一の正規表現クエリで Any compilation body.... 行と IBM first used the term.... 行を返す必要があります。

複数行の文字列を一致させるために考えられる解決策

この特定の問題の解決策について説明する前に、正規表現 (正規表現) API のさまざまな側面、特にソリューション全体で頻繁に使用される側面を理解することが不可欠です。

それでは、re.compile() から始めましょう。

Python re.compile() メソッド

re.compile() は正規表現パターンを正規表現オブジェクトにコンパイルし、match()search() などのメソッドで使用できるようにします。

コンパイルされていないパターンに対する re.compile() の利点の 1つは、再利用性です。 コンパイルされていないパターンごとに新しい文字列を宣言する代わりに、コンパイルされた式を複数回使用できます。

import re as regex

pattern = regex.compile(".+World")
print(pattern.match("Hello World!"))
print(pattern.search("Hello World!"))

出力:

<re.Match object; span=(0, 11), match='Hello World'>
<re.Match object; span=(0, 11), match='Hello World'>

Python re.search() メソッド

re.search() は文字列内で一致を検索し、一致が見つかれば Match オブジェクトを返します。複数の一致が存在する場合、最初のインスタンスを返します。

re.compile() を使用せずに直接使用することもできます。これは、1つのクエリのみを作成する必要がある場合に適用されます。

import re as regex

print(regex.search(".+World", "Hello World!"))

出力:

<re.Match object; span=(0, 11), match='Hello World'>

Python re.finditer() メソッド

re.finditer() は、文字列内のパターンに一致し、重複しないすべての一致に対して Match オブジェクトを提供するイテレータを返します。

次に、イテレータを使用して一致を反復処理し、必要な操作を実行できます。 一致は、見つかった順序で、文字列の左から右に並べられます。

import re as regex

matches = regex.finditer(r"[aeoui]", "vowel letters")
for match in matches:
    print(match)

出力:

<re.Match object; span=(1, 2), match='o'>
<re.Match object; span=(3, 4), match='e'>
<re.Match object; span=(7, 8), match='e'>
<re.Match object; span=(10, 11), match='e'>

Python re.findall() メソッド

re.findall() は、文字列内のパターンの重複しないすべての一致のリストまたはタプルを返します。 文字列は左から右にスキャンされます。 そして、一致は発見された順に返されます。

import re as regex

# Find all capital words
string = ",,21312414.ABCDEFGw#########"
print(regex.findall(r"[A-Z]+", string))

出力:

['ABCDEFG']

Python re.MULTILINE メソッド

re.MULTILINE の重要な利点は、^ が文字列の先頭だけでなく、すべての行の先頭でパターンを検索できることです。

Python 正規表現記号

正規表現記号は、複雑な方法で使用すると、すぐに非常に混乱する可能性があります。 以下は、これらのシンボルの基本的な概念をよりよく理解するために、ソリューションで使用されているシンボルの一部です。

  • ^ は行頭の位置をアサートします
  • String は (大文字と小文字を区別する) 文字 "String" と文字通り一致します
  • . すべての文字に一致します (行末に使用される記号を除く)
  • + は、以前に指定されたトークンに可能な限り一致します。
  • \n は改行文字に一致します
  • \r は (CR) キャリッジ リターン記号に一致します
  • ? 0-1回の間の前のトークンと一致します
  • +? 1 から infinite 回の間で前のトークンに一致します。可能な限り少なくします。
  • a-z は、az の間の範囲の 1 文字に一致します (大文字と小文字を区別します)。

re.compile() を使用して Python で複数行のテキスト ブロックを照合する

さまざまなパターンを使用して理解しましょう。

パターン 1: 既知のパターンに re.search() を使用する

コード例:

import re as regex

multiline_string = "Regular\nExpression"
print(regex.search(r"^Expression", multiline_string, regex.MULTILINE))

出力:

<re.Match object; span=(8, 18), match='Expression'>

上記の式は、(^ により) まず行頭の位置を主張し、次に "Expression" の正確な出現箇所を検索します。

MULTILINE フラグを使用すると、最初の行だけでなく、各行で "Expression" の出現がチェックされるようになります。

パターン 2: 未知のパターンには re.search() を使用する

コード例:

import re as regex

data = """Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.\n
\n
IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.
"""

result = regex.compile(r"^(.+)(?:\n|\r\n)+((?:(?:\n|\r\n?).+)+)", regex.MULTILINE)

print(result.search(data)[0].replace("\n", ""))

出力:

Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.

正規表現は、読みやすくするために、分割して小さなチャンクに単純化できます。

最初のキャプチャ グループ (.+) では、行内の各文字が一致します (行末記号に対応する記号を除く)。 このプロセスは可能な限り頻繁に行われます。

その後、非キャプチャ グループ (?:\n|\r\n) で、行末記号のみ、または行末記号と改行ができるだけ多く一致します。

2つ目の捕捉グループ ((?:(?:\n|\r\n?).+)+) については、非捕捉グループ ((?:(?:\n|\r\n?).+)+) 改行文字または改行文字とキャリッジ リターンのいずれかが最大 1 回一致します。

すべての文字は、行末記号を除いて、非キャプチャ グループの外側で一致します。 この手順は、可能な限り何度でも実行されます。

パターン 3: 未知のパターンには re.finditer() を使用する

コード例:

import re as regex

data = """Regex In Python

Regex is a feature available in all programming languages used to find patterns in text or data.
"""

query = regex.compile(r"^(.+?)\n([\a-z]+)", regex.MULTILINE)

for match in query.finditer(data):
    topic, content = match.groups()
    print("Topic:", topic)
    print("Content:", content)

出力:

Topic: Regex In Python
Content: 
Regex is a feature available in all programming languages used to find patterns in text or data.

上記の式は、次のように説明できます。

最初のキャプチャ グループ (.+?) では、すべての文字が (以前のように行末記号を除いて) 可能な限り少なく一致します。 その後、単一の改行文字 \n が一致します。

改行文字を一致させた後、次の操作は 2 番目のキャプチャ グループ (\n[a-z ]+) で実行されます。 最初に改行文字が照合され、続いて a-z の間の文字が可能な限り何度も照合されます。

re.findall() を使用して Python で複数行のテキスト ブロックを照合する

コード例:

import re as regex

data = """When working with regular expressions, the sub() function of the re library is an invaluable tool.

the subroutine looks over the string for the given pattern and applies the given replacement to all instances where it is found.
"""

query = regex.findall("([^\n\r]+)[\n\r]([a-z \n\r]+)", data)

for results in query:
    for result in results:
        print(result.replace("\n", ""))

出力:

When working with regular expressions, the sub() function of the re library is an invaluable tool.
the subroutine looks over the string for the given pattern and applies the given replacement to all instances where it is found

正規表現の説明をよりよく理解するために、各グループに分けて、各部分が何をするかを見てみましょう。

最初のキャプチャ グループ ([^\n\r]+) では、改行記号またはキャリッジ リターン文字を除くすべての文字が可能な限り一致します。

その後、式 [\n\r] で文字がキャリッジ リターンまたは改行のいずれかである場合に一致が行われます。

2 番目のキャプチャ グループ ([a-z \n\r]+) では、a-z または改行またはキャリッジ リターンの間の文字が可能な限り多く一致します。

著者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

関連記事 - Python Regex