Python問題集を解いてみよう!!

【Python】文字列の括弧の中身を抜き出したい

当ページのリンクには広告が含まれています。
文字列の括弧の中身を抜き出す

LINEのオープンチャットに投稿された質問に回答したので、ご紹介します。

今回は「Python初心者🔰」というオープンチャットに投稿されたものです。

この記事を書いている時点では218名の方が参加されています。

Python関連の中では3番目に参加人数の多いオープンチャットです。

おすすめのレンタルサーバー
目次

質問

Pyボーイ

[‘タナカ[TANAKA]No1, ‘サトウ[SATO]NoA2’, ‘ナカムラ[NAKAMURA]No3’]

これを下記のようにカッコ内のみ抽出して、リスト型に整形したいのですがうまくできません💦

[‘TANAKA’, ‘SATO’, ‘NAKAMURA’]

回答

まずは回答したコードです。

import re

text_list = ['タナカ[TANAKA]No1', 'サトウ[SATO]NoA2', 'ナカムラ[NAKAMURA]No3']

pattern = '(?<=\[).*(?=\])'

text_list_re_search = [re.search(pattern, text).group() for text in text_list]

print(text_list_re_search)

上記の実行結果

['TANAKA', 'SATO', 'NAKAMURA']

reモジュールは標準モジュールなので、pip等でインストールする必要はありません。

解説

今回の質問の要件はこんな感じ。

  • 文字列から括弧の中身だけ抜き出す
  • その文字列が複数あり、リスト形式になっている

文字列を特定の条件で抜き出したり、編集したい場合は正規表現を使うことが多いです。

今回も正規表現を使います。

これが1つ目のポイントです。

次に、その文字列が複数あり、リスト形式にまとめられているという点。

これはリスト内包表記を使うと簡単に書くことができます。

これが2つ目のポイントです。

では、順番に見ていきましょう。

正規表現

Python では正規表現のための機能が標準モジュールとして用意されています。

reというモジュールです。

正規表現は英語で「Regular expressions」なので、reという名前になっています。(たぶん)

前述しましたが、標準モジュールなので、インストールは不要です。

今回はreモジュールのsearch()メソッドを使用しました。

その名前の通り、条件に合う文字列を探すメソッドです。

search()メソッドは引数に条件(パターン)と文字列を指定します。

条件(パターン)

今回使用した条件(パターン)は(?<=\[).*(?=\])です。

何の情報もなく、これだけ見ると暗号ですね。。。

これを3つに分解します。(?<=\[).*(?=\])です。

まず最も簡単な.*です。

Pythonの正規表現では.は「任意の1文字」、*は「0回以上の繰り返し」という意味です。

つまり、.*は全ての文字列が該当しますし、空文字列も該当します。

次の1つ目の(?<=\[)です。これは「後読み」とか「肯定の後読み」と言われるパターンで、この場合は「 [ の後ろの〜」という意味になります。

例えば、「『pre』の後ろ」と指定したい場合は、(?<=pre)と書きます。

Pyボーイ

あれ?「 \ 」は?

って思いますよね。\はエスケープシーケンスです。[は正規表現の条件(パターン)の表記として意味を持っていきます。ただ、今回はただの文字列として [を使いたいため、\[と書く必要があります。

最後に(?=\])です。これは「先読み」、「肯定の先読み」と言われるパターンで、この場合は「]の前の〜」という意味になります。後読みの逆ですね。ここでもエスケープシーケンス\を使っています。

ということで、3つ組み合わせると、「[の後ろで、]の前の、任意の文字列」という意味になります。

search()メソッド

search()メソッドについては、返り値が特殊な型になっています。

次のコードで、search()メソッドの返り値を確認してみます。

import re

sample_text = '1234abcde56789'

search_result = re.search('\D+', sample_text)

print(search_result)
print(type(search_result))

上記の実行結果

<re.Match object; span=(4, 9), match='abcde'>
<class 're.Match'>

search()メソッドの返り値は「re.Match」型で、元も文字列のどの部分が条件(パターン)に一致したのか、一致した文字列、の情報が含まれています。

また、この「re.Match」型には一致した文字列を取得するgroup()メソッドが用意されています。

import re

sample_text = '1234abcde56789'

search_result = re.search('\D+', sample_text)

print(search_result.group())

上記の実行結果

abcde

回答のコードではこれらをつなげてre.search(〜).group()と書いています。

リスト内包表記

リスト内包表記の最もシンプルな書き方は、

[変数の処理 for 変数 in シーケンス]

という形式になります。

具体的な例をいくつか見てみます。

num_list = [i for i in range(1, 101)]

print(num_list)
上記の実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
num_list2 = [j**2 for j in range(1, 10)]

print(num_list2)
上記の実行結果
[1, 4, 9, 16, 25, 36, 49, 64, 81]
num_list = [i for i in range(1, 101)]

num_list3 = [k for k in num_list if k % 5 == 0]

print(num_list3)
上記の実行結果
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]

どれも、リスト内包表記を使わなくても書くことはできますが、コードがシンプルになったり、内容によっては処理時間が短くなったりもします。

今回の回答も、リスト内包表記を使わないで書くと次のようになります。

import re

text_list = ['タナカ[TANAKA]No1', 'サトウ[SATO]NoA2', 'ナカムラ[NAKAMURA]No3']

pattern = '(?<=\[).*(?=\])'

text_list_re_search = []

for text in text_list:
    re_search_result = re.search(pattern, text).group()
    text_list_re_search.append(re_search_result)

print(text_list_re_search)

こっちのほうが見やすい、分かりやすい、という人もいるかもしれませんね。

おすすめのPython参考書

Google Colaboratory

今回も、コードの動作は Google Colaboratory で確認しました。

掲載したコードは下記から確認できます。

環境構築の不要な Google が提供している Webサービスなので、Python を学習中の方にはオススメです。

おわりに

今回は、

文字列の括弧の中身だけ抜き出す方法

を紹介しました。

また、ポイントである、

  • 正規表現(re.search)
  • リスト内包表記

について簡単に解説をしました。

以上です。

スポンサーリンク

文字列の括弧の中身を抜き出す

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次