柔軟に働き方を選ぶ時代に必要なこと >>

http://okwave.jp/qa/q8693280.html

以前したこの質問を参考に正規表現を使ったプログラムを書いているのですが

以下のような3行からなるテキストデータ(例)から「ひらがな一文字」「かたかな一文字」の単語のみを除去したいと思っております。

(例)
単語 あ 語句 みち 空 ジャンプ
無理 ぃ お 暮らし ホーミング
石 防止 ゾ あなた

URLの質問を参考に(\bでは除去できなかったので)

for line in textfile:
 line = re.sub(u'\s[ぁ-ゞ]\s', u' ', line)
 line = re.sub(u'\s[ァ-ヾ]\s', u' ', line)

としたらうまく「ひらがな一文字」「かたかな一文字」を除去できました。
しかし、次の例のように一つ目の単語にこれらがきた場合手前にスペースがないので除去できません(4行目の「ま」が除去できない)

単語 あ 語句 みち 空 ジャンプ
無理 ぃ お 暮らし ホーミング
石 防止 ゾ あなた
ま 空白 みどり

だからといって
[ぁ-ゞ]\s
のようにすると、例えば一行目は「単語 語句 み空 ジャンプ」のように一文字でない単語の最後にひらがな・カタカナがくるとその部分を除去し、後ろの単語と結合してしまうという不具合がおきてしまいます。

扱うデータ的に、行の頭にスペースを入れるということはしたくありません。(はじめに入れて後から消すといっても正規表現に当てはまった行はスペースがなくなり、そうでないところはあるといったバラバラな状況が発生するのでそれもしたくありません)


これらをふまえて、うまく「ひらがな一文字」「カタカナ一文字」を除去する方法・正規表現はあるでしょうか。(今書いているプログラムはこのFor文のみなので、別で行が追加される分にはかまいません。)

よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

\b を回答した者です。

日本語は「語」と見なされないようでダメみたいですね。

しょうがないので、
 line = re.sub(u'\s[ぁ-ゞァ-ヾ]\s', u' ', line)
 line = re.sub(u'\A[ぁ-ゞァ-ヾ]\s', u'', line)
 line = re.sub(u'\s[ぁ-ゞァ-ヾ]\Z', u'', line)
と行中、行頭、行末と3回に分けて。
    • good
    • 0
この回答へのお礼

再度ありがとうございます!助かります
参考にやってみます

お礼日時:2014/08/05 16:48

せっかくなので、正規表現について勉強しましょう。



正規表現 HOWTO
http://docs.python.jp/2/howto/regex.html
7.2. re — 正規表現操作
http://docs.python.jp/2.7/library/re.html

\bについては、2つの罠にハマっています。

一つは、上記HOWTOにもあるものです
http://docs.python.jp/2/howto/regex.html#more-me …
> \b
> 単語の境界。(略)
> この特別なシーケンスを利用するときには二つの微妙な点を心にとめておく必要があります。
> まずひとつめは Python の文字列リテラルと表現の間の最悪の衝突を引き起すことです。
> Python の文字列リテラルでは \b は ASCII 値8のバックスペース文字です。
> raw string を利用していない場合、Python は \b をバックスペースに変換し、正規表現は期待するものとマッチしなくなります。

もう一つは、reモジュールの説明の方にあります。
> \b
> 空文字列とマッチしますが、単語の先頭か末尾の時だけです。
> 単語は英数字あるいは下線文字の並んだものとして定義されています (略)
> 英数字であると見なされる文字の正確な集合は、 UNICODE と LOCALE フラグの値に依存することに注意して下さい。

つまり、現状は、ひらがなは「単語の一部ではない」と見做されている状態です。

対策としては
・UNICODEフラグONでcompileしたreのオブジェクトを使う。
コンパイル済みの正規表現オブジェクトの使い方はHOWTOにも書いてあります。
forの外でcompileすると、forの中では、毎回正規表現をコンパイルする必要が無くなり、効率の向上が期待できます。

・(?u)で、UNICODEフラグを設定する
> (?iLmsux)
> ( 集合 'i', 'L', 'm', 's', 'u', 'x' から1文字以上) 。
> 文字は、正規表現全体の対応するフラグ (re.I (大文字・小文字を区別しない), re.L (ロケール依存), re.M (MULTILINEモード), re.S (DOTALLモード), re.U (Unicode依存), re.X (冗長) ) を設定します。



あと、\s だと 無理 ぃ お 暮らし ホーミング の「お」にマッチしません。
「お」の前の空白が、「ぃ」の後の空白としてマッチしてしまうため、続きが「お」からになるからです。
    • good
    • 0
この回答へのお礼

ありがとうございました!非常に参考になりました

お礼日時:2014/08/05 16:48

行頭の1文字あるいは行末の1文字を削除する正規表現を追加してみては如何でしょうか?



line = re.sub(u'^[ぁ-ゞ]\s', u' ', line)
line = re.sub(u'\s[ぁ-ゞ]\s', u' ', line)
line = re.sub(u'\s[ぁ-ゞ]$', u' ', line)
    • good
    • 0
この回答へのお礼

ありがとうございました!参考にさせていただき勉強してみます

お礼日時:2014/08/05 16:47

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


人気Q&Aランキング