วิธีการตรวจสอบว่าตัวละครปัจจุบันเป็นตัวอักษร


9

ฉันจะทราบได้อย่างไรว่าตัวละครปัจจุบันเป็นตัวอักษร (ตัวอักษรตัวอักษร) (เช่นเป็นของคลาสไวยากรณ์[:alpha:]ในความคิด regexp) ฉันต้องการเขียนฟังก์ชั่นง่าย ๆ ดังต่อไปนี้:

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

อัปเดต น่าเสียดายที่สมมติฐานของฉันเกี่ยวกับความเท่าเทียมกันของคลาสของตัวอักษรและคลาสไวยากรณ์[:alpha:]ดูเหมือนจะเป็นเท็จ

คำตอบ:


9

ใช้คุณสมบัติถ่าน Unicode

สิ่งนี้ควรใช้งานได้:

(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เป็นตัวพิมพ์ใหญ่และไม่ถามฉันว่าคนอื่น ๆ )


ขอบคุณมาก, แก้ปัญหานี้ด้วย۱۲۳۴۵۶۷۸۹۰แต่มีบาง-เชิงลบที่แท้จริงเช่นภาษาอาหรับหรือภาษาฮิบรู Alef: ,א ا
ชื่อ

@ ชื่อคงที่ ลองอีกครั้ง.
Malabarba

2
ขอขอบคุณอีกครั้ง. ฉันตรวจสอบด้วยตัวอักษรต่างๆและใช้งานได้ ยกเว้นอย่างเดียวที่ฉันพบคือมีบางตัวอักษรในเอเชียเช่นจีนen.wikipedia.org/wiki/Chinese_numeralsหรือญี่ปุ่นen.wikipedia.org/wiki/Japanese_numerals ยกตัวอย่างเช่นถือเป็นตัวเลข5ในภาษาญี่ปุ่น รหัสของคุณพิจารณาจดหมายนี้ อาจเป็นตัวอักษร (เช่นในตัวเลขโรมันv) บางทีคนที่คุ้นเคยกับญี่ปุ่นก็สามารถยืนยันสิ่งนี้ได้
ชื่อ

1
เป็นเหมือนคำภาษาอังกฤษfiveดังนั้นจึงเป็นตัวอักษร เมื่อเขียนหมายเลข 5 แทนคำที่ห้าพวกเขาใช้5ภาษาอังกฤษเหมือนกัน
Muir

8

แก้ไข:คำตอบนี้ควรจะสมบูรณ์ใน 25.5 (ที่ข้อผิดพลาดได้รับการแก้ไข) สำหรับรุ่นเก่าใช้ตัวเลือกอื่น


สิ่งนี้ควรบอกคุณว่าถ่านปัจจุบันเป็นตัวอักษรและควรทำงานในภาษาใดก็ได้

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

ขอบคุณมากฉันแค่อยากรู้เกี่ยวกับความแตกต่างระหว่างการlooking-at-pใช้ในการแก้ปัญหาของคุณและlooking-atในคำตอบอื่น ๆ
ชื่อ

1
ฟังก์ชันทั้งสองนั้นเทียบเท่ากันยกเว้นlooking-at-pว่าไม่ได้ตั้งค่าข้อมูลที่ตรงกัน
jch

1
@Name มองไปที่ p อยู่ใกล้กับเพรดิเคตที่บริสุทธิ์เนื่องจากไม่ได้ตั้งค่าข้อมูลการจับคู่ หากก่อนหน้านี้คุณทำอะไรบางอย่างเช่นการค้นหาไปข้างหน้าmatch-string(และพี่น้องหลายคน) จะส่งคืนผลลัพธ์ของการค้นหา ในขณะที่เวอร์ชันที่ไม่ใช่ภาคแสดงการจับคู่สตริงจะส่งคืนผลลัพธ์ของการจับคู่ที่ดู
Malabarba

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

ขอบคุณอีกครั้ง อีกข้อผิดพลาดที่เป็นบวก: สิ่งนี้พิจารณา۹(เช่นตัวเลขอินเดีย 9) หรือ٪เป็นตัวอักษร
ชื่อ

1
วิธีแก้ปัญหาแรกของคุณใช้ได้ดีกับตัวอักษรกรีก (เช่นζหรือα) แต่การอัปเดตไม่ได้
ชื่อ

แต่การรวมเข้าด้วยกันเป็นวิธีที่ใกล้กว่า
ชื่อ

2

ในกรณีที่คุณมีความกังวลมากเกี่ยวกับตัวละครแห่งชาติและการรักษาที่แม่นยำของ Unicode ชั้นเรียนตัวอักษรแล้วทางออกเดียวที่ฉันสามารถที่จะหาเพื่อให้ห่างไกลเป็นงูหลามห้องสมุดregex ทั้งสองgrepและPerl(ฉันประหลาดใจที่สุด!) ทำงานไม่ถูกต้อง

\p{L}ดังนั้นการแสดงออกปกติคุณหลังจากเป็นหนึ่งในนี้: นี้เป็นที่รู้จักในฐานะรุ่นคุณสมบัติ Unicode ชวเลขเวอร์ชันเต็มหรือแม้กระทั่ง \p{Letter} ตัวเองเป็นชั้นคอมโพสิต แต่ฉันจะไม่ไปลงรายละเอียดอ้างอิงที่ดีที่สุดที่ฉันสามารถหาในเรื่องที่เป็นที่นี่p\{General_Category=Letter}Letter

Python library ไม่ได้มีอยู่แล้วในภาษา (เป็นอีกทางเลือกหนึ่งของreLibrary ในตัว) ดังนั้นคุณจะต้องติดตั้งตัวอย่างเช่น:

# 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.