現在の文字が文字かどうかを判断する方法


9

現在の文字が文字(英字)であるかどうか(つまり、[:alpha:]正規表現で構文クラスに属しているかどうか)を判別する方法。以下のような簡単な関数を書きたいと思います:

(defun test-letter () (interactive)
(if char-after-is-a-letter
    (message "This is a letter")
    (message "This is not a letter")
    )
)

更新 残念ながら、文字のクラス[:alpha:]と構文クラスの同等性に関する私の仮定は誤っているようです。

回答:


9

Unicode charプロパティを使用する

これは間違いなく動作するはずです:

(memq (get-char-code-property (char-after) 'general-category)
      '(Ll Lu Lo Lt Lm Mn Mc Me Nl))

ボーナスとして、それはまたより速いはずですlooking-at


Emacsは、Unicode標準で指定されたすべての文字プロパティを格納します。でアクセスできますget-char-code-property。具体的には、general-categoryプロパティはどの文字が文字であるかを指定します(Ll小文字でLu大文字で、他の文字については尋ねません)。


多くのおかげで、これはとの問題を解決し۱۲۳۴۵۶۷۸۹۰ますが、いくつかの真の陰性、例えばアラビア語やヘブライ語のアレフがありますאا
名前

@名前が修正されました。もう一回やってみよう。
マラバルバ2015

2
ありがとうございました。いろいろなアルファベットで調べてみましたが動作しました。私が見つけた唯一の例外は、中国語のen.wikipedia.org/wiki/Chinese_numeralsや日本語のen.wikipedia.org/wiki/Japanese_numeralsなどのアジアのアルファベットです。たとえば、日本語の数字と見なされ5ます。あなたのコードはこれを手紙とみなします。多分それは手紙です(ローマ数字のようにv)。たぶん日本語に詳しい人ならこれを確認できるでしょう。
名前

1
は英語の単語のfiveようで、文字です。5という単語の代わりに5を書くとき、彼らは5英語のように使用します。
Muir、

8

編集:この回答は25.5(バグ修正されていた)では完全に有効です。古いバージョンの場合は、他のオプションを使用してください。


これにより、現在の文字が文字であるかどうかがわかり、どの言語でも機能するはずです。

 (looking-at-p "[[:alpha:]]")

多くの感謝、私はlooking-at-pあなたの解決策とlooking-at他の答えで使用された違いに興味があります。
名前

1
looking-at-p一致データを設定しないことを除いて、2つの関数は同等です。
jch 2015

1
@Name looking-at-pは、一致データを設定しないため、純粋な述語に近いです。以前に前方検索のようなものを実行した場合match-string(およびその多くの兄弟)は、検索結果を返します。一方、非述語バージョンでは、match-stringは、looking-atマッチの結果を返します。
マラバルバ2015

5

私はあなたがこれで逃げることができると思います:

(defun test-letter ()
  (interactive)
  (let ((char (char-after)))
    (if (and (eq (char-syntax char) ?w)
             (or (> char ?9)
                 (< char ?1)))
        (message "This is a letter")
      (message "This is not a letter"))))

更新

これは効率は落ちますが、あなたが望むものに近いです:

(defun test-letter ()
  (interactive)
  (if (looking-at "[a-z-A-Z]")
      (message "This is a letter")
    (message "This is not a letter")))

ありがとう、考えられる問題:この関数は数字(123 ...)を文字と見なします。
名前

簡単に修正できます。
abo-abo 2015

改めて感謝いたします。別の誤検知:これは۹(インドの数字9)または٪文字と見なされます。
名前

1
最初の解決策はギリシャ文字(ζまたはなどα)で問題ありませんでしたが、更新はそうではありません。
名前

しかし、両方を組み合わせる方がより近いソリューションです。
名前

2

国別文字とUnicode文字クラスの正確な扱いについて非常に懸念している場合、私がこれまでに見つけた唯一の解決策はPython regexライブラリです。grepPerl(私の驚いたことに!)両方が適切に仕事をしませんでした。

したがって、あなたが求めている正規表現は次のとおり\p{L}です。これはUnicodeプロパティの短縮形として知られており、完全版は\p{Letter}またはp\{General_Category=Letter}です。 Letterそれ自体は複合クラスですが、詳細には触れません。この件に関して私が見つけた最良のリファレンスはここにあります

Pythonライブラリは言語に組み込まれていません(組み込みライブラリの代替reです)。したがって、たとえば次のようにインストールする必要があります。

# pip install regex

その後、次のように使用できます。

import regex
>>> regex.match(ur'\p{L}+', u'۱۲۳۴۵۶۷۸۹۰')
>>> regex.match(ur'\p{L}+', u'абвгд')
<regex.Match object; span=(0, 5), match=u'\u0430\u0431\u0432\u0433\u0434'>
>>> regex.match(ur'\p{L}+', u'123')
>>> regex.match(ur'\p{L}+', u'abcd')
<regex.Match object; span=(0, 4), match=u'abcd'>
>>> 

このスクリプトは、アクセスできる場所に置くこともできます。

#!/usr/bin/env python
import regex
import sys

if __name__ == "__main__":
    for match in regex.finditer(ur'\p{L}+', sys.argv[1].decode('utf-8')):
        print match.string

そして、Emacsから次のように呼び出します(このスクリプトをに保存したとします~/bin)。

(defun unicode-character-p ()
  (interactive)
  (let* ((current (char-after (point)))
         (result (shell-command-to-string
                  (format "~/bin/is-character.py '%c'" current))))
    (message
     (if (string= result "") "Character %c isn't a letter"
        "Character %c is a letter")
     current)))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.