pythonで正規表現を用いて条件に合致するフィールドを全て抽出する
問題はタイトルのように、現在、正規表現でマッチングできるフィールドは以下の3種類しかないことです。
re.match()
re.search()
re.findall()
簡単に紹介すると、re.match() は re.search() と非常によく似ています。主な違いは、前者は対象の文字列の先頭からマッチするのに対し、後者はこの要件を必要としないことです。主な違いは、前者は対象となる文字列の先頭からマッチするが、後者はその必要がないことである。一方、re.findall()は、マッチの結果をすべて返すことができる。しかし、re.findall()が前の二つと同じ結果を返さないこともあります。次の例を見てみましょう。
文の場合。
発病以来、腰痛、頚部痛、咽頭痛、口腔内潰瘍、光アレルギー、脱毛、口渇、ドライアイ、四肢の突発性打撲、四肢の脱力、むくみ、泡状尿、精神、食欲、睡眠、直近1ヶ月の乾便、5~6日1回、腹痛、黒便、血便、1~2時間尿、排尿痛なし、血尿なし、。体重は大きな変化は見られませんでした。
正規ルールを使用して、尿および尿に関する句を含むすべての句にマッチさせたいと思います。目的は、"腫れなし、泡状の尿 "と "1回1~2時間排尿、痛みなし、血尿 "を識別することです。これらの句を識別して返すことである。
re.findall()でマッチングさせようと思っていたのですが。
import re
lines = [
"Since the beginning of the disease, the patient has no low back pain, neck pain, no sore throat, oral ulcers, no light allergy, hair loss, no dry mouth, dry eyes, no episodic bruising of the extremities, no weakness of the limbs, no swelling, foamy urine, poor mental health, appetite, sleep, dry stools in the past month, once every 5-6 days, no abdominal pain, black stools, blood in the stool, urination once every 1-2 hours, no painful urination, hematuria. There is no significant change in body weight. ",
for line in lines]
for line in lines:
pattern = "[,;. ,;.] +[^,;. ,;.] *((pee)|urine) +[^,;. ,;.] *[,;. ,;.] +"
str = re.findall(pattern,line)
print(str)
その結果
[('尿', '), ('尿', 'おしっこ')]である。
ここで使っているパターンの意味を説明すると、節をマッチングさせようとしているので、節の前後には必ず対応する記号が入るので、パターンの前後に「[,;. ,;.] +」を付け、「+」は少なくとも1つマッチすることを意味します。そして、「[,;. ,;.] *」は、句読点「,;.」を除いて0個以上一致することを意味する。は中国語と英語のコンマ、セミコロン、ピリオドにそれぞれ付加され、"*"は0または1以上一致することを意味する。なお、「[,;. ,;.]」を使うのは
「というのも、テキストには上記の例の「-」のように、他の記号がたくさん含まれている場合があるからです。漢字や数字、特定の記号を使ってマッチさせたい場合は、足りない部分があるかもしれませんし、私の目的はマッチした節だけを取得することなので、「[^,;. ,;.]
"であれば、もう少し汎用性があります。次に「((pee)|urine)」ですが、これは「pee」または「urine」を含む部分文字列にマッチすることを意味します。
しかし、re.findall()を使って得られた結果は私が望んでいたものではなかったので、マッチングルールを少し変えて、"((urine|urine)+"を"[(urine|urine)+"に置き換えた。このマッチングの適用性を確認するために、さらに二つのサンプルを追加してみた。さらに2つのサンプルを追加してみました。全体の結果は以下の通りです。
import re
lines = [
"Since the beginning of the disease, the patient has no low back pain, neck pain, no sore throat, oral ulcers, no light allergy, hair loss, no dry mouth, dry eyes, no episodic bruising of the extremities, no weakness of the limbs, no swelling, foamy urine, poor mental health, appetite, sleep, dry stools in the past month, once every 5-6 days, no abdominal pain, black stools, blood in the stool, urination once every 1-2 hours, no painful urination, hematuria. There is no significant change in body weight. ",
"Since the beginning of the disease, sleep, normal stomach, normal urine, in the past 4-5 years, 3-4 times a day, mostly yellow-brown formed soft stool, occasionally rotten stool, a sense of incomplete defecation, blood in the stool, black stool, no wasting. ",
" short stature, lighter weight than peers. "
for line in lines]
for line in lines:
pattern = "[,;. ,;.] +[^,;. ,;.] *[(pee)urine] +[^,;. ,;.] *[,;. ,;.] +"
str = re.findall(pattern,line)
print(str)
その結果
['むくみ、泡状尿がない','最近1ヶ月の便が乾燥している','腹痛、黒色便、血便がない','排尿痛、血尿がない']]といった特徴があります。
[尿は正常」「便はほとんどが黄褐色の軟便」「排便は不完全」。]
[]
の「尿1~2時間1回、排尿痛なし、血尿あり」がマッチアウトしなかったこと、そして、便に関する「過去1ヶ月の乾燥便」でも「(尿)尿」の意味が「尿」または「尿」を含む部分集合にマッチしないようです。 または「尿」。では「(尿)尿」の意味は「小」「うんち」「尿」を含む部分列にはマッチするか?"と "urine "に一致するか?しかし、"small "を含むが "poo "と "pee "を含まない3番目のサンプルによれば、上記の考え方はまだ正しくない。
さらにre.findall()は原文の部分文字列の最初と最後が一致しないので、"1回1-2時間排尿、排尿痛なし、血尿 "を取得したいです。これも2つの節が連結されていると、なかなか出てきません。
そこで、もう一つの非常に一般的なメソッドであるre.search()に目をつけました。
import re
lines = [
"Since the beginning of the disease, the patient has no low back pain, neck pain, no sore throat, oral ulcers, no light allergy, hair loss, no dry mouth, dry eyes, no episodic bruising of the extremities, no weakness of the limbs, no swelling, foamy urine, poor mental health, appetite, sleep, dry stools in the past month, once every 5-6 days, no abdominal pain, black stools, blood in the stool, urination once every 1-2 hours, no painful urination, hematuria. There is no significant change in body weight. ",
for line in lines]
for line in lines:
pattern = "[,;. ,;.] +[^,;. ,;.] *((pee)|urine) +[^,;. ,;.] *[,;. ,;.] +"
str = re.search(pattern, line)
print(str.group())
その結果
,むくみがなく、尿が泡立つ。
見ての通り、re.search()は条件を満たす最初の部分文字列にのみマッチします。
また、パターンの「((尿)|pee)」を「[(尿)|pee]」(または「[(尿)pee]」、意味は全く同じ。 も試しました)に修正しました。
得られた結果は
,ふくらみがない、尿が泡立っている。
ご覧の通り、変更前と変更後では変化がありませんが、原文の「むくみのない、泡のような尿」から「尿」を取り除くと、変更前の結果は次のようになります。
1~2時間に1回排尿する。
修正後の結果は
過去1ヶ月間、乾燥した便がある。
については、以下の通りです。
pattern = "[,;. ,;.] +[^,;. ,;.] *[(pee)urine] + [^,;. ,;.] *[,;. ,;.] +"
re.findall()かre.search()のどちらかで、うんこ関連の部分文字列にマッチングします。
そして、そのために
pattern = "[,;. ,;.] +[^,;. ,;.] *((urine)|urine) +[^,;. ,;.] *[,;. ,;.] +"
re.findall()とre.search()でマッチした部分文字列は、プレマッチの結果がタプルを含むリストである点で異なります。[一方、後者のマッチでは、次のような部分文字列が欲しいのです:,No floaters, foamy urine,
その後、同僚に聞いて、さらに正規の動作の仕組みを理解したところ、括弧()には、マッチした文字列を抽出する以外に、グループ化を捉える役割もあり、マッチした後に括弧の中の内容を保存し、呼び出した時に対応する値を返すことがわかりました。re.findall()を使用すると、格納されたグループの全ての値が返されます。
わかりやすくするために、上記のパターンの「((pee)|pee)」を「((pee)|(pee))」に置き換えます、例.
pattern = "[,;. ,;.] +[^,;. ,;.] *((pee)|(urine)) +[^,;. ,;.] *[,;. ,;.] +"
re.findall()を使った出力は以下の通りです。
[('尿', '', '尿'), ('尿', 'おしっこ', '')]。
上のように、「((pee)|(urine))」では「()」が3つ使われているので、3つのグループ化が行われ、一番外側のグループ化で「pee」または「原文ではpeeもurineもマッチするので1位には両方がある」を捕捉します。2番目のグルーピングは「(尿)」を捕捉するために使用されるので、2番目のグルーピングには「尿」だけが格納されます。同様に、3番目のグルーピングは「(尿)」を捕捉するために使用されるので、結果には「尿」だけが格納されます。
そして、グループ化された結果を出力するためにre.search()を使っています。
for line in lines:
pattern = "[,;. ,;.] +[^,;. ,;.] *((おしっこ)|(尿)) + [^,;. ,;.] *[,;. ,;.] +"
str = re.search(pattern, line)
print(str.group(0))する。
print(str.group(1))
print(str.group(2))する。
プリント(str.group(3))
その結果、次のようになります。
、むくみがない、尿が泡立つ。
尿
なし
アール
group(1), group(2), group(3) はそれぞれ ('urine', '', 'urine') の対応するグループ化結果と同じである。しかし、ここではgroup(0)(またはgroup()、全く同じ意味)は「('尿', '', '尿')」ではなく、ここで著者は限定的でその理由はあまり明確ではありません。つまり、group(0)を呼ぶと、patternの()の意味はグループを捕捉することではなくなり、マッチする文字列を抽出するという本来の意味に戻るのです。
を解決するために
pattern = "[,;. ,;.] +[^,;. ,;.] *[(pee)urine] + [^,;. ,;.] *[,;. ,;.] +"
うんこ」を含む不要な文字列のマッチングの問題は、捕捉しないグループ化(?)を使用することで解決できます。
pattern = "[,;. ,;.] ? [^,;. ,;.] *(? :pee|urine) [^,;. ,;.] *[,;. ,;.] "
これは、"pee "または "urine "にマッチします。
[',むくみ、泡状尿がない',',排尿1~2時間',',排尿痛、血尿がない']。
上記の結果に注意してください。「,1-2時間1回排尿」と「痛くない排尿、血尿」が直後にあり、前者にカンマが割り当てられているため、後者にはその後カンマがなく、文字列がスライスされて消えているように見えるので、ここではパターン中の最初の「[,;. ,;.] 」の後の「+」は、前の文字の出現回数0回か1回という意味の「?」( )に置き換えられます;もちろんさらに最適化すると、次のようになります。
pattern = "[,;. ,;.] ? [^,;. ,;.] *(? :pee|piss). *? [,;. ,;.] "
2番目の「[^,;. ,;.」があることがわかります。]
" を ".
?"
すべての節がマッチして出力されますが、隣接する2つの節は別々に出力され、これはまだ私たちが望むものではありません。そこで、上記のコードを次のように改良した。
for line in lines:
#pattern = "[,;. ,;.] +[^,;. ,;.] *[('pee')urine] +[^,;. ,;.] *[,;. ,;.] +"
pattern = "[,;. ,;.] ? [^,;. ,;.] *? (? :pee|urine). *? [,;. ,;.] "
#pattern = "[,;. ,;.] ? [^,;. ,;.] *(? :pee|urine) [^,;. ,;.] *[,;. ,;.] "
str = re.findall(pattern,line)
ls = [',', ';', '.' ,'',',';','.']
for idx, text in enumerate(str):
if text[0] not in ls:
str[idx-1] += text
str.remove(text)
print(str)
その結果
[',ふくらみ、泡状の尿がない',1回1~2時間の尿、排尿痛、血尿がない']。
また、re.search()を使えば、期待通りの結果を得ることも可能で、そのコードは以下の通りです。
{{コード
という結果になります。
[浮き輪なし、泡状尿」、「排尿1~2時間1回、排尿痛なし、血尿あり」]。
pythonで正規表現を使って条件を満たすすべてのフィールドを抽出するというこの記事は、より関連するpythonの正規表現でフィールドの内容を抽出することを紹介しています、BinaryDevelopの過去の記事を検索するか、以下の関連記事を引き続き閲覧してくださいBinaryDevelopをよりサポートしていただけると幸いです!。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン