Làm thế nào để xác định nếu ký tự hiện tại là một chữ cái


9

Làm thế nào tôi có thể xác định nếu ký tự hiện tại là một chữ cái (một ký tự chữ cái) (nghĩa là thuộc về lớp cú pháp [:alpha:]trong các khái niệm regrec). Tôi muốn viết một chức năng đơn giản như dưới đây:

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

Cập nhật Thật không may, giả định của tôi về sự tương đương của lớp các chữ cái và lớp cú pháp [:alpha:]dường như là sai.

Câu trả lời:


9

Sử dụng thuộc tính char Unicode

Điều này chắc chắn sẽ làm việc:

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

Như một phần thưởng, nó cũng sẽ nhanh hơn looking-at.


Emacs lưu trữ tất cả các thuộc tính ký tự được chỉ định bởi tiêu chuẩn Unicode. Họ có thể truy cập với get-char-code-property. Cụ thể, thuộc general-categorytính chỉ định các ký tự là chữ cái ( Lllà chữ thường, Luchữ hoa và đừng hỏi tôi những ký tự khác là gì).


Rất cám ơn, điều này giải quyết vấn đề với ۱۲۳۴۵۶۷۸۹۰nhưng có một số tiêu cực thực sự, ví dụ tiếng Ả Rập hoặc tiếng Do Thái Alef: א, ا.
Tên

@ Tên đã sửa. Thử lại lần nữa.
Malabarba

2
Cám ơn bạn một lần nữa. Tôi đã kiểm tra nó với các bảng chữ cái khác nhau và nó hoạt động. Ngoại lệ duy nhất tôi tìm thấy là với một số bảng chữ cái châu Á như tiếng Trung en.wikipedia.org/wiki/Chinese_numemony hoặc tiếng Nhật en.wikipedia.org/wiki/Japanese_numemony . Ví dụ được coi là số 5trong tiếng Nhật. Mã của bạn coi đây là một lá thư. Có thể đó là một chữ cái (như trong số La Mã v). Có lẽ ai đó quen thuộc với tiếng Nhật có thể xác minh điều này.
Tên

1
giống như từ tiếng Anh five, vì vậy nó là một chữ cái. Khi viết số 5 thay vì từ năm, họ sử dụng 5giống như tiếng Anh.
Muir

8

EDIT: Câu trả lời này phải hoàn toàn hợp lệ trong 25.5 (trong đó lỗi đã được sửa). Đối với các phiên bản cũ hơn, sử dụng tùy chọn khác .


Điều này sẽ cho bạn biết nếu char hiện tại là một chữ cái, và nên hoạt động trong bất kỳ ngôn ngữ nào.

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

Rất cám ơn, tôi chỉ tò mò về sự khác biệt giữa looking-at-pđược sử dụng trong giải pháp của bạn và looking-attrong câu trả lời khác.
Tên

1
Hai chức năng tương đương nhau, ngoại trừ việc looking-at-pkhông đặt dữ liệu khớp.
JCH

1
@Name looking-at-p gần với một vị từ thuần túy hơn, vì nó không đặt dữ liệu khớp. Nếu trước đây bạn đã thực hiện một cái gì đó như chuyển tiếp tìm kiếm, match-string(và nhiều anh chị em của nó) sẽ trả về kết quả tìm kiếm. Trong khi đó, với phiên bản không vị ngữ, chuỗi kết hợp sẽ trả về kết quả của kết quả tìm kiếm.
Malabarba

5

Tôi nghĩ bạn có thể thoát khỏi điều này:

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

Cập nhật

Đây là một cách ít hiệu quả hơn, nhưng gần hơn với những gì bạn muốn:

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

Cảm ơn, một vấn đề có thể xảy ra: Hàm này coi các chữ số (123 ...) là một chữ cái.
Tên

Dễ dàng sửa chữa.
abo-abo

Rất cám ơn một lần nữa. Một dương tính giả khác: Điều này xem xét ۹(tức là chữ số 9 của Ấn Độ) hoặc ٪như một chữ cái.
Tên

1
Giải pháp đầu tiên của bạn là ổn với các chữ cái Hy Lạp (chẳng hạn như ζhoặc α), nhưng bản cập nhật thì không.
Tên

Nhưng kết hợp cả hai là một giải pháp gần gũi hơn.
Tên

2

Trong trường hợp bạn rất quan tâm đến các ký tự quốc gia và xử lý chính xác các lớp ký tự Unicode, thì giải pháp duy nhất tôi có thể tìm thấy cho đến nay là regexthư viện Python . Cả grepPerl(với sự ngạc nhiên hoàn toàn của tôi!) Đã không thực hiện công việc đúng cách.

Vì vậy, biểu thức chính quy bạn theo sau là cái này : \p{L}. Đây được gọi là phiên bản tốc ký thuộc tính Unicode, phiên bản đầy đủ \p{Letter}hoặc thậm chí p\{General_Category=Letter}. Letterbản thân nó là một lớp tổng hợp, nhưng tôi sẽ không đi vào chi tiết, tài liệu tham khảo tốt nhất tôi có thể tìm thấy về chủ đề này ở đây .

Thư viện Python không được tích hợp vào ngôn ngữ (nó là một thay thế cho rethư viện tích hợp). Vì vậy, bạn sẽ cần phải cài đặt nó, ví dụ:

# pip install regex

Sau đó, bạn có thể sử dụng nó như vậy:

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

Bạn cũng có thể đặt đoạn script này ở nơi bạn có thể truy cập nó:

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

Và gọi nó từ Emacs như vậy (giả sử bạn đã lưu tập lệnh này vào ~/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)))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.