質問: re.sub(u'\s[ァ-ヾ]\s', u' ', line) としたらうまく「ひらがな一文字」「かたかな一文字」を除去できました。 しかし、次の例のように一つ目の単語にこれらがきた場合手前にスペースがないので除去できません(4行目の「ま」が除去できない) 単語 あ 語句 みち 空 ジャンプ 無理 ぃ お 暮らし ホーミング 石 防止 ゾ あなた ま 空白 みどり だからといって [ぁ-ゞ]\s のようにすると、例えば一行目は「単語 語句 み空 ジャンプ」のように一文字でない単語の最後にひらがな・カタカナがくるとその部分を除去し、後ろの単語と結合してしまうという不具合がおきてしまいます。 扱うデータ的に、行の頭にスペースを入れるということはしたくありません。(はじめに入れて後から消すといっても正規表現に当てはまった行はスペースがなくなり、そうでないところはあるといったバラバラな状況が発生するのでそれもしたくありません) これらをふまえて、うまく「ひらがな一文字」「カタカナ一文字」を除去する方法・正規表現はあるでしょうか。(今書いているプログラムはこのfor文のみなので、別で行が追加される分にはかまいません。) よろしくお願いします。
回答: せっかくなので、正規表現について勉強しましょう。 正規表現 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-metacharacters > \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 だと 無理 ぃ お 暮らし ホーミング の「お」にマッチしません。 「お」の前の空白が、「ぃ」の後の空白としてマッチしてしまうため、続きが「お」からになるからです。