質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

6回答

1173閲覧

正規表現でカッコ内の文字列を抽出したい

muryayan

総合スコア7

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/11/17 03:47

前提・実現したいこと

x = 'ABC (abc) (def)'
y = 'ABC (efg)'
という2つの文字列があり、正規表現を使って後ろの括弧だけから文字列を抜きだしたい。
xからは'def'、yからは'efg'を抜き出したい。
以下のコードではyは意図したとおりに抜き出せたが、xではコードを変更する必要がありそう。
同じコードでどちらも意図したように文字列を抜き出せないでしょうか?

これは単純化した例で、文字列はもっと複雑で、3文字では無いです。
括弧の数は例のように1~2個で、2個の場合は半角スペースで隣接しています。

該当のソースコード

Python

1#In 2x = 'ABC (abc) (def)' 3y = 'ABC (efg)' 4 5pattern=re.compile(r'(?<=().+(?=))') 6x_result=pattern.search(x).group().strip() 7y_result=pattern.search(y).group().strip() 8print (x_result) 9print (y_result) 10 11#Out 12abc) (def 13efg 14

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

単純に、

Python

1for a in ["ABC (abc) (def)","ABC (efg)"]: 2 b = re.search(r".*((.*?))",a) 3 print(b.group(1))

でいいかと思います。
前半に最長マッチである.*を書けば最後の括弧がヒットします。

投稿2021/11/17 10:39

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muryayan

2021/11/17 12:58

ありがとうございます!そんなに簡単に正規表現で後ろの括弧から抜き出せるとは驚きました。 ".*?((.*?))"とすれば、最初の括弧から抜き出すこともできるのですね。
itagagaki

2021/11/17 14:12

もう言うまでもないと思いますが、これも予期せず()を含まないテキストを食ったらエラーになっちゃうのでお気を付けを。余計なおせっかいでした。
otn

2021/11/17 14:24

実際のプログラムに組み込む時はそうですね。
muryayan

2021/11/18 00:52

おせっかいなんてとんでもないです。何万件かのデータ処理しているので、今後括弧がないデータが出てくる可能性もあります。itagagakiさんのコードも参考にさせていただています。
guest

0

質問にある、

x = 'ABC (abc) (def)' y = 'ABC (efg)'

という二つの入力サンプルから、何をどこまで前提としてよいのか? がはっきりしていると、より分かりやすい正規表現で対応できるかと思います。たとえばサンプルから読み取れる、入力文字列の条件として

  • 入力文字列の最後の文字は ) である。
  • 対になる () とに囲まれる部分は[a-z]+ (あるいは、\w+など) としておけば事足りる。

というものなのであれば、以下でよいかと思います。

python3

1import re 2 3x = 'ABC (abc) (def)' 4y = 'ABC (efg)' 5 6regexp = r'(\w+))$' 7 8m = re.search(regexp, x) 9 10for text in [x, y]: 11 m = re.search(regexp, text) 12 if m: 13 print(m.group(1)) 14 15

出力結果:

def

efg

追記1

正規表現を使うというのがお題なのだとは思いますが、必ずしも正規表現を使わずとも、以下でもよいのではないかと思えました。

python3

1x = 'ABC (abc) (def)' 2y = 'ABC (efg)' 3 4for text in [x, y]: 5 lastword = text.split(' ').pop().strip('()') 6 print(lastword) 7

出力結果:

def

efg

追記2

コメントから頂きました、

実際の文字列内にはスペースもあるので、

というのは、() で囲まれた文字列にはスペース(などの空白記号)が含まれる可能性がある、ということと解釈しました。そうだとすると、確かに上記の追記1 だと対応できませんね。

() で囲まれた文字列の前提条件としては、

  • () は含まれない

という制約のみとしつつも、split を使えないか?と考えると、正規表現モジュールresplit を使って、これでもいけそうです。

Python3

1import re 2 3x = 'ABC (ab c) (d ef)' 4y = 'ABC (e f g)' 5 6for text in [x, y]: 7 lastword = re.split(r'[()]', text)[-2] 8 print(lastword) 9

出力結果:

d ef

e f g

投稿2021/11/17 05:12

編集2021/11/17 10:06
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muryayan

2021/11/17 05:55

なるほど。正規表現を使わなくても出来そうですね。 確かに正規表現もそんなに簡単にできるのですね。大変参考になりました。 ありがとうございました。
muryayan

2021/11/17 06:21

実際の文字列内にはスペースもあるので、やはり正規表現は必要なようです。質問に前提条件をしっかり記載していなくてすみません。
退会済みユーザー

退会済みユーザー

2021/11/17 10:13

コメントありがとうございます。 > 実際の文字列内にはスペースもあるので、やはり正規表現は必要なようです。 とのことでしたので、回答に正規表現モジュールの split を使った案を追記しました。 > 質問に前提条件をしっかり記載していなくてすみません。 いえ、問題ございませんですよ???? 正規表現を問うご質問で、入力文字列の満たす、必要かつ十分な条件を記述するのは難しいと思います。私の回答ふくめ、みなさんのご回答を参考にしながら、実際に取り組まれている課題を解決するための正規表現に求める要件(入力は何を前提にしてよくて、正規表現にどこまでやってもらうか?)を見直しされていけばよいかと思います。
muryayan

2021/11/17 12:52

ありがとうございます!そんな解き方もあるのですね。色々参考になります。
guest

0

Python

1import re 2 3def inLastParen(text): 4 pattern = re.compile(r'((.*?))') 5 groups = pattern.findall(text) 6 return groups[-1] if len(groups) > 0 else '' 7 8x = 'ABC (abc) (def)' 9y = 'ABC (efg)' 10z = 'ABC xxx' 11 12print (inLastParen(x)) 13print (inLastParen(y)) 14print (inLastParen(z))

投稿2021/11/17 04:18

編集2021/11/17 06:50
itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muryayan

2021/11/17 04:46

ありがとうございます。match.lastindexというのがあるのですね。勉強になりました。
muryayan

2021/11/17 06:28

inLastParen(x)でabcが表示されるのですが、なぜでしょうか?defの方を表示させたいのですが。
itagagaki

2021/11/17 06:54

すみません。コードにミスがありましたので修正しました。 searchではなくmelianさんの回答のようにfindallを使うべきでしたね。 なのでBAはmelianの回答でいいと私は思うのですが、私が余計なおせっかいをしたようですみません。
muryayan

2021/11/17 08:47

修正ありがとうございます。皆さんから色々な解法を教えていただき、大変勉強になりました!
guest

0

今のコードを活かしたいなら、次のようなパタンでしょうか。

python

1# 後ろのカッコが文字列の最後の場合 2pattern = re.compile(r'(?<=()[^()]*(?=)$)') 3 4# 後ろのカッコ以降も文字がある場合 5pattern = re.compile(r'(?<=()[^()]*(?=)[^()]*$)')

.(全部)を[^()](カッコ以外)に変更したのと、
閉じカッコ以降にカッコが出てこないという条件を追加しています。

投稿2021/11/17 04:45

bsdfan

総合スコア4794

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muryayan

2021/11/17 05:23

なるほど。括弧以外の文字列だけ抽出して、末尾の括弧閉じるとマッチさせるのですね。 解読に時間がかかりました。。。 ありがとうございます。
guest

0

python

1import re 2 3x = 'ABC (abc) (def)' 4y = 'ABC (efg)' 5 6pattern = re.compile(r'((.*?))') 7x_result = re.findall(pattern, x)[-1].strip() 8y_result = re.findall(pattern, y)[-1].strip() 9 10print(x_result) 11print(y_result) 12 13# 14def 15efg

投稿2021/11/17 04:06

melian

総合スコア20655

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muryayan

2021/11/17 04:45

なるほど。カッコ内をfindallで全て抽出して、[-1]でリストの一番後ろの文字列を選べば良いのですね。 ありがとうございました!
itagagaki

2021/11/17 04:59

リストが空の場合はエラーになっちゃうと思うので気を付けてください。
melian

2021/11/17 05:00

> 括弧の数は例のように1~2個で
itagagaki

2021/11/17 05:02

例外はあり得ないからこのコードで良いのだということをおっしゃりたいのですね。
muryayan

2021/11/17 05:16

そうですね。括弧がないという例外は今のところ無いです。
melian

2021/11/17 05:19 編集

ええ、もしも任意個という条件でしたら、 x_result = m[-1].strip() if (m := re.findall(pattern, x)) else '' としていたでしょう(Python 3.8 以降のみ)。
itagagaki

2021/11/17 05:37

実装の現場で、もし万が一想定外のデータが来たときのことも考えておかないと不具合の原因になりますから注意してくださいねと申し上げたまでですよ。
melian

2021/11/17 06:00

> itagagaki 実装の現場を想定していましたか、さすがです。 > muryayan muryayan さん、ベストアンサーの座は謹んで辞退しますので、itagagaki さんを含め、他の回答者にお与え下さい。
guest

0

あらかじめ文字列内に ( が何回出てくるかをcountで確認しておいて、1回出てくる場合と2回出てくる場合で正規表現を分けるのはダメなのでしょうか?
正規表現だけで実装する方法は自分だとわからないですね。

投稿2021/11/17 04:03

irognodyci

総合スコア227

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問