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

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

ただいまの
回答率

91.36%

  • Python

    3812questions

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

  • 正規表現

    568questions

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

  • Perl

    338questions

    Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Perlの正規表現による文字列抽出をPythonでやりたい

解決済

回答 3

投稿 2017/11/21 09:16 ・編集 2017/11/21 21:09

  • 評価
  • クリップ 1
  • VIEW 156

troublemaker

score 1

下記のようなPerlのコードと同じことをPythonでやりたくて調べています。

    use utf8;
    use feature 'unicode_strings';
    use open ':encoding(utf8)';         # I/O default encoding is UTF-8
    use open ':std';                    # stdio encoding = utf8
    use Encode qw(encode_utf8 decode);

    use strict;

    my $regExp = qr/[\p{Han}\p{Katakana}a-zA-Z0-90-9%][\p{Han}\p{Katakana}a-zA-Z0-90-9%・ー]*/;
    my $text = "三人行えば、必ずわが師あり";
    my @matchedList = ();

    for ($text) {
        s/($regExp)/ do{ push @matchedList,$1; ""; }; /ge;
    }

    print join( ",",@matchedList);

上記を実行すると、"三人行,必,師"という漢字だけを抽出した文字列を得ることができます。
これをPythonでもやりたいのですが、下記のようなコードを書いてみてもうまくいかず困っています。

    # coding: utf-8
    import re

    regExp = r'[一-龥ァ-ンa-zA-Z0-90-9%][一-龥ァ-ンa-zA-Z0-90-9%・ー]*'
    text = '三人行えば、必ずわが師あり'

    if re.match(regExp, text):
        matched = re.findall(regExp, text)
        print ','.join(matched)

これでは漢字のみを抽出することができず、一文すべてを抽出してしまい結果が異なります。
re.searchなども試してみましたが同様でした。
PythonでもPerlで書いたような抽出結果を再現することはできるのでしょうか。
お知恵をお貸し下さい。
よろしくお願いいたします。

追記:
ご回答頂き無事解決できました。
ありがとうございました。

# coding: utf-8
import re

regExp = ur'[一-龥ァ-ンa-zA-Z0-90-9%][一-龥ァ-ンa-zA-Z0-90-9%・ー]*'
text = u'三人行えば、必ずわが師あり'

if re.match(regExp, text):
    matched = re.findall(regExp, text)
    print ','.join(matched).encode('utf-8')
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+6

文字データはユニコード文字列として処理しなければならない、という点はほかの方が回答しておられますので省きます。


Pythonのreが対応している正規表現には、Perlの拡張正規表現にある\p{用字}のようなものがありません。同じことができる文字クラスを書くしかないと思います。

特定の用字を[一-龥][ァ-ン]のように単一のコード範囲で表すことは、一般にできません。ユニコードではバージョンが上がるごとに文字の追加があるため、同じ用字の文字がコード表のあちこちに散らばって登録されているのが普通です。

  • [一-龥]は、ユニコードの最初のバージョンの1.0.0で登録されていた漢字しかカバーできません。
  • [ァ-ン]は、ユニコード1.0.0さえもカバーしていません。などが含まれません。後のバージョンで追加されたアイヌ語用拡張などはもちろんカバーできません。

ユニコードコンソーシアムが、ユニコード10.0.0での用字プロパティの完全な一覧を公開しています。これをもとにして正規表現を作ることができます。

  • \p{Han}と同等の文字クラス
[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303A\u303B\u3400-\u4DB5\u4E00-\u9FEA\uF900-\uFA6D\uFA70-\uFAD9\U00020000-\U0002A6D6\U0002A700-\U0002B734\U0002B740-\U0002B81D\U0002B820-\U0002CEA1\U0002CEB0-\U0002EBE0\U0002F800-\U0002FA1D]
  • \p{Katakana}と同等の文字クラス
[\u30A1-\u30FA\u30FD-\u30FE\u30FF\u31F0-\u31FF\u32D0-\u32FE\u3300-\u3357\uFF66-\uFF6F\uFF71-\uFF9D\U0001B000]


となります。

U+10000以降の文字を省いたら正規表現が少しは簡単になるのでは……と思うかもしれませんが、そうしないほうがいいです。特にU+20000以降の漢字には、日本語のテキストデータで普通に使われているものがいくつもあります。

ちなみに、ユニコードのバージョンが上がると文字が追加されますから、上記の正規表現も見直す必要があります。特に漢字は追加される頻度が高いです。


 クローズ後追記

濁点 、半濁点 、音引き  は、用字プロパティがKatakanaではなくCommonやInheritedになっています。ので、「片仮名の一文字」にマッチさせるには\p{Katakana}だけでは十分でなく、次のようにする必要があると思います。

[\p{Katakana}\u30FC\uFF70][\u3099-\u309C\uFF9E\uFF9F]?
[\u30A1-\u30FA\u30FD-\u30FE\u30FF\u31F0-\u31FF\u32D0-\u32FE\u3300-\u3357\uFF66-\uFF6F\uFF71-\uFF9D\U0001B000\u30FC\uFF70][\u3099-\u309C\uFF9E\uFF9F]?

[\u3099-\u309C\uFF9E\uFF9F]が濁点と半濁点、[\u30FC\uFF70]が音引きです。

投稿 2017/11/21 13:57

編集 2017/11/22 13:13

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/21 21:03

    ご回答ありがとうございました。
    正規表現の書き方の間違いも指摘して頂けて助かりました。
    コード自体は動くようになったので、今度は正規表現の方も工夫したいと思います。

    キャンセル

  • 2017/11/22 13:15

    濁点などについて気がついたことを追記しました。

    キャンセル

  • 2017/11/23 08:01

    追記ありがとうございます!

    キャンセル

+2

多分 お使いの Pythonは Python2系だと思います。Python2では日本語を扱う時はunicode文字列として指定してください。 regExp, text ともに unicode文字列にしたら期待通りに動きました。

regExp = ur'([一-龥ァ-ンa-zA-Z0-90-9%][一-龥ァ-ンa-zA-Z0-90-9%・ー]*)'
text = u'三人行えば、必ずわが師あり'

print ','.join(re.findall(regExp, text)) => 三人行,必,師

投稿 2017/11/21 10:08

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/21 21:04

    教えて頂いた通りunicodeに変換して動かすことができました!
    ご回答ありがとうございました。

    キャンセル

+1

下記のように対応してみました。

# coding: utf-8
import re

regExp = u'[一-龍]+'
text = u'三人行えば、必ずわが師あり'

if re.match(regExp, text):
   matched = re.findall(regExp, text)
   print(','.join(matched))
   # => 三人行,必,師

投稿 2017/11/21 10:01

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/21 21:05

    unicode文字列にすれば良かったんですね!
    参考になりました。
    ご回答ありがとうございました。

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

同じタグがついた質問を見る

  • Python

    3812questions

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

  • 正規表現

    568questions

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

  • Perl

    338questions

    Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。