Cara menentukan apakah karakter saat ini adalah huruf


9

Bagaimana saya dapat menentukan apakah karakter saat ini adalah huruf (karakter alfabet) (yaitu, milik kelas sintaks [:alpha:]dalam pengertian regexp). Saya ingin menulis fungsi sederhana seperti di bawah ini:

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

Pembaruan Sayangnya, asumsi saya tentang kesetaraan kelas huruf dan kelas sintaksisnya [:alpha:]keliru.

Jawaban:


9

Gunakan properti char Unicode

Ini pasti bekerja:

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

Sebagai bonus juga harus lebih cepat daripada looking-at.


Emacs menyimpan semua properti karakter yang ditentukan oleh standar Unicode. Mereka dapat diakses dengan get-char-code-property. Secara khusus, general-categoryproperti menentukan karakter mana yang huruf ( Llhuruf kecil, Luhuruf besar, dan jangan tanya saya apa yang lain).


Terima kasih banyak, ini menyelesaikan masalah dengan ۱۲۳۴۵۶۷۸۹۰tetapi ada beberapa yang benar-negatif, misalnya Arab atau Ibrani Alef: א, ا.
— Nama

@Nama Diperbaiki. Coba lagi.
— Malabarba

2
Terima kasih lagi. Saya memeriksanya dengan berbagai Abjad dan berfungsi. Satu-satunya pengecualian yang saya temukan adalah dengan beberapa alfabet Asia seperti Cina en.wikipedia.org/wiki/Chinese_numerals atau Jepang en.wikipedia.org/wiki/Japanese_numerals . Misalnya 五dianggap sebagai angka 5dalam bahasa Jepang. Kode Anda menganggap ini surat. Mungkin itu surat (seperti dalam nomor romawi v). Mungkin seseorang yang terbiasa dengan bahasa Jepang dapat memverifikasi ini.
— Nama

1
五seperti kata bahasa Inggris five, jadi itu adalah huruf. Saat menulis angka 5 dan bukan kata lima, mereka menggunakan 5seperti bahasa Inggris.
— Muir

8

EDIT: Jawaban ini harus benar-benar valid dalam 25.5 (di mana bug telah diperbaiki). Untuk versi yang lebih lama, gunakan opsi lain .


Ini akan memberi tahu Anda jika karakter saat ini adalah surat, dan harus berfungsi dalam bahasa apa pun.

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

Terima kasih banyak, saya hanya ingin tahu tentang perbedaan antara yang looking-at-pdigunakan dalam solusi Anda dan looking-atjawaban yang lain.
— Nama

1
Kedua fungsi tersebut setara, kecuali yang looking-at-ptidak mengatur data kecocokan.
— jch

1
@Name looking-at-p lebih dekat dengan predikat murni, karena tidak mengatur data kecocokan. Jika sebelumnya Anda melakukan sesuatu seperti pencarian-maju, match-string(dan banyak saudara kandungnya) akan mengembalikan hasil pencarian. Sementara itu, dengan versi non-predikat, match-string akan mengembalikan hasil pertandingan yang terlihat.
— Malabarba

5

Saya pikir Anda bisa lolos dengan ini:

(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"))))

Memperbarui

Ini kurang efisien, tetapi lebih dekat dengan yang Anda inginkan:

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

Terima kasih, masalah yang mungkin terjadi: Fungsi ini menganggap angka (123 ...) sebagai huruf.
— Nama

Mudah diperbaiki.
— abo-abo

Terima kasih banyak lagi. Lain positif palsu: Ini menganggap ۹(yaitu, angka 9 India) atau ٪sebagai surat.
— Nama

1
Solusi pertama Anda baik-baik saja dengan huruf-huruf Yunani (seperti ζatau α), tetapi pembaruannya tidak.
— Nama

Tetapi menggabungkan keduanya adalah solusi yang lebih dekat.
— Nama

2

Jika Anda sangat prihatin tentang karakter nasional dan perlakuan tepat terhadap kelas karakter Unicode, maka satu-satunya solusi yang saya dapat temukan sejauh ini adalah regexpustaka Python . Keduanya grepdan Perl(mengejutkan saya!) Tidak melakukan pekerjaan dengan benar.

Jadi, ekspresi reguler Anda setelah satu ini: \p{L}. Ini dikenal sebagai versi steno properti Unicode, versi lengkapnya adalah \p{Letter}atau bahkan p\{General_Category=Letter}. Letteritu sendiri adalah kelas komposit, tapi saya tidak akan pergi ke rincian, referensi terbaik yang bisa saya temukan pada subjek ada di sini .

Pustaka Python tidak terintegrasi ke dalam bahasa (ini adalah alternatif untuk repustaka bawaan). Jadi, Anda harus menginstalnya, misalnya:

# pip install regex

Kemudian, Anda bisa menggunakannya seperti ini:

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'>
>>> 

Anda juga dapat meletakkan skrip ini di suatu tempat di mana Anda dapat mengaksesnya:

#!/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

Dan panggil saja dari Emacs seperti itu (misalkan Anda menyimpan skrip ini di ~/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)))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.