none
正規表現で日本語とアルファベットを切り分けたいのですが RRS feed

  • 質問

  • お世話になります.Windows7, EXCEL2010のVBAで日本語とアルファベットを切り分ける処理を書いていたのですが,一箇所上手く切り分けられない現象が発生したので質問させて下さい.下記のコードですが,"乳類MILKS"の要素のみ正規表現がマッチしません.他の文字列は切り分けられますのでパターン文字列が悪いわけではなさそうですが...原因と対処法をご享受下さい.

    Sub RegExpSample()
    Dim tmpAr       As Variant
    Dim myAr()      As String
    Dim i           As Long
    Dim strPtn      As String
    Dim myRegExp    As Object
    Dim myMatches   As Object
    Dim myMatch     As Object
    Dim strTarget   As String
    tmpAr = Array("穀類CEREALS", _
                    "いも及びでん粉類POTATOES", _
                    "豆類PULSES", _
                    "種実類NUTS", _
                    "野菜類VEGETABLES", _
                    "果実類FRUITS", _
                    "きのこ類MUSHROOMS", _
                    "藻類ALGAE", _
                    "魚介類FISHES", _
                    "肉類MEATS", _
                    "卵類EGGS", _
                    "乳類MILKS", _
                    "し好飲料類BEVERAGES", _
                    "調味料及び香辛料類SEASONINGS")
    strPtn = "^([ぁ-ヶ]|[亜-黑])+([A-Z]|[a-z])"
    Set myRegExp = CreateObject("VBScript.RegExp")
    With myRegExp
        .Pattern = strPtn
        .ignorecase = True
        .Global = True
    End With
    For i = LBound(tmpAr) To UBound(tmpAr)
        ReDim Preserve myAr(i)
        Set myMatches = myRegExp.Execute(tmpAr(i))
        On Error Resume Next
        Set myMatch = myMatches.Item(0)
        On Error GoTo 0
        myAr(i) = myMatch.Value
    Next i
    End Sub
    
    


    2012年2月6日 1:25

回答

  • 正規表現はもっときれいに書けます。

    "^([ぁ-ヶ]|[亜-黑])+([A-Z]|[a-z])"  → "^([ぁ-ヶ亜-黑])+([A-Za-z])" (アルファベットは1文字だけマッチすればいいの?)

    で、問題は、 亜-黑 という範囲が正しいのかということです。漢字は今後もどんどん追加されていきますから、この範囲が永久に正しいということは絶対にありえません。発想を転換して、「アルファベット以外」「アルファベット」という分け方で考えてみてはどうでしょうか? こうすると正規表現は

    "^([^A-Za-z]+)" (後半のアルファベットの方はマッチしても使われないようなので省略)

    とできます。

    • 回答としてマーク じふ 2012年2月6日 4:59
    2012年2月6日 1:54

すべての返信

  • 正規表現はもっときれいに書けます。

    "^([ぁ-ヶ]|[亜-黑])+([A-Z]|[a-z])"  → "^([ぁ-ヶ亜-黑])+([A-Za-z])" (アルファベットは1文字だけマッチすればいいの?)

    で、問題は、 亜-黑 という範囲が正しいのかということです。漢字は今後もどんどん追加されていきますから、この範囲が永久に正しいということは絶対にありえません。発想を転換して、「アルファベット以外」「アルファベット」という分け方で考えてみてはどうでしょうか? こうすると正規表現は

    "^([^A-Za-z]+)" (後半のアルファベットの方はマッチしても使われないようなので省略)

    とできます。

    • 回答としてマーク じふ 2012年2月6日 4:59
    2012年2月6日 1:54
  • ありがとうございます.意図通りに動作しました.

    確かに漢字のコードは増えていく可能性がありますね.

    後学のために教えていただきたいのですが,マッチングの仕様は最大限マッチするところまで,でしょうか.それともあり得るマッチ全てを取り出すのでしょうか.

    2012年2月6日 3:18
  • 「最大限マッチするところまで」と「あり得るマッチ全て」の違いがわかりませんでした。 

    正確な「仕様」は正規表現エンジンごとに異なります。今回なら「VBScript.RegExp」の仕様がどうなのか、ということになります。

    何を聞かれているのかわかりませんが ^ (文字列の先頭)に該当する個所はそもそも1ヶ所しかないはず…。

    2012年2月6日 5:07
  • 違いがわかりませんでした

    失礼しました.例でしか表現できないのですが・・・

    "果実類FRUITS"に対して"^([^A-Za-z]+)"でマッチさせた結果は"果実類"一つしか得られませんが,"果"や"果実"はマッチしないのか,という意味でした.

    http://msdn.microsoft.com/ja-jp/library/cc392176.aspx

    上記ページに『'*'、'+'、'?' の各修飾子はすべて、最大一致として動作します。つまり、できるだけ広い範囲のテキストに一致しようとします』とありますので,疑問は解決しました.

    ありがとうございました.

    2012年2月6日 5:34
  • 例えば、VBAでなくVBで使われる、.NET Frameworkの正規表現だと *? という量指定子があります。 * なら最長ですし、 *? なら最短になります。
    # Perl由来なので、Perlでも同じ指定ができます。

    というように、正規表現はエンジンごとにできることが変わりますので、一般論で仕様を答えるのはあえて避けました。

    2012年2月6日 5:41
  • ありがとうございました.勉強になりました.
    2012年2月6日 6:07