Geçerli karakterin bir harf olup olmadığını belirleme


9

Geçerli karakterin bir harf olup olmadığını nasıl belirleyebilirim (alfabetik bir karakter) (yani normal [:alpha:]ifadelerde sözdizim sınıfına aittir ). Aşağıdaki gibi basit bir işlev yazmak istiyorum:

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

Güncelleme Ne yazık ki, harflerin ve sözdizimi sınıfının denkliği hakkındaki varsayımım [:alpha:]yanlış gibi görünüyor.

Yanıtlar:


9

Unicode char özelliklerini kullanma

Bu kesinlikle işe yarayacaktır:

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

Bir bonus olarak daha hızlı olmalı looking-at.


Emacs , Unicode standardında belirtilen tüm karakter özelliklerini saklar . Onlar ile erişilebilir get-char-code-property. Özellikle, general-categoryözellik hangi karakterlerin harf olduğunu belirtir ( Llküçük harf, Lubüyük harf ve diğerlerinin bana ne olduğunu sorma).


Çok teşekkürler, bu sorunu çözer, ۱۲۳۴۵۶۷۸۹۰ancak Arapça veya İbranice Alef gibi bazı gerçek olumsuzluklar vardır: א, ا.
İsim

@Ad Sabit. Tekrar dene.
Malabarba

2
Tekrar teşekkürler. Çeşitli alfabelerle kontrol ettim ve işe yarıyor. Bulduğum tek istisna Çince en.wikipedia.org/wiki/Chinese_numerals veya Japanese en.wikipedia.org/wiki/Japanese_numerals gibi Asya alfabesi ile ilgili . Örneğin Japonca sayı olarak kabul edilir 5. Kodunuz bunu bir harf olarak kabul eder. Belki bir harftir (roma numarasında olduğu gibi v). Belki Japonca bilen biri bunu doğrulayabilir.
İsim

1
İngilizce kelimeye benziyor five, bu yüzden bir mektup. Beş kelime yerine 5 rakamını yazarken, 5İngilizce gibi kullanırlar .
Muir

8

EDIT: Bu yanıt 25.5 ( hatanın giderildiği yerde) mükemmel geçerli olmalıdır . Daha eski sürümler için diğer seçeneği kullanın .


Bu size mevcut karakterin bir harf olup olmadığını ve herhangi bir dilde çalışması gerektiğini söylemelidir.

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

Çok teşekkürler, sadece looking-at-pçözümünüzde ve looking-atdiğer yanıtta kullanılanlar arasındaki farkı merak ediyorum .
Adı

1
İki işlev eşdeğerdir, ancak looking-at-peşleme verileri ayarlanmamıştır.
jch

1
@N-bakarak-p saf bir yükleme daha yakındır, çünkü eşleşme verilerini ayarlamaz. Daha önce ileriye doğru arama gibi bir şey yaptıysanız match-string(ve birçok kardeşi) aramanın sonucunu döndürür. Bu arada, yüklem olmayan sürümde, eşleme dizesi, seyir eşleşmesinin sonucunu döndürür.
Malabarba

5

Sanırım bununla kurtulabilirsin:

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

Güncelleme

Bu daha az verimli, ancak istediğiniz şeye daha yakın:

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

Teşekkürler, olası bir sorun: Bu işlev rakamları (123 ...) harf olarak kabul eder.
İsim

Kolayca sabitlenebilir.
abo-abo

Tekrar çok teşekkürler. Başka bir yanlış pozitif: Bu ۹(yani Hint rakamı 9) veya ٪bir harf olarak düşünür .
Adı

1
İlk çözümünüz Yunan harfleriyle ( ζveya gibi α) iyiydi , ancak güncelleme iyi değil.
İsim

Ancak her ikisini birleştirmek daha yakın bir çözümdür.
Adı

2

Ulusal karakterler ve Unicode karakter sınıflarının hassas muamelesi konusunda çok endişeliyseniz, o zamana kadar bulabildiğim tek çözüm Python regexkütüphanesi . Hem grepve Perl(benim için sürpriz!) İşi düzgün yapmadı.

Yani, peşinde normal ifadeniz biridir: \p{L}. Bu Unicode özelliği kısayol sürümü olarak bilinir, tam sürüm \p{Letter}hatta p\{General_Category=Letter}. Letterkendisi bileşik bir sınıf, ama ayrıntılara girmeyeceğim, bu konuda bulabileceğim en iyi referans burada .

Python kütüphanesi dilde yerleşik değildir (yerleşik kütüphaneye bir alternatiftir re). Yani, yüklemeniz gerekir, örneğin:

# pip install regex

Sonra, şöyle kullanabilirsiniz:

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

Bu komut dosyasını erişebileceğiniz bir yere de koyabilirsiniz:

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

Ve bu şekilde Emacs'tan çağırın (bu komut dosyasını kaydettiğinizi varsayalım ~/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)))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.