在Emacs lisp中检查字符串是否全部为大写?

在Emacs lisp中检查字符串是否全部为大写?,emacs,lisp,elisp,capitalization,Emacs,Lisp,Elisp,Capitalization,全部。我想知道Emacs lisp是否有一个内置函数,用于检查字符串是否完全由大写字符组成。以下是我现在正在使用的: (setq capital-letters (string-to-list "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) (defun chars-are-capitalized (list-of-characters) "Returns true if every character in a list of characters is a capital

全部。我想知道Emacs lisp是否有一个内置函数,用于检查字符串是否完全由大写字符组成。以下是我现在正在使用的:

(setq capital-letters (string-to-list "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))

(defun chars-are-capitalized (list-of-characters)
  "Returns true if every character in a list of characters is a capital         
letter. As a special case, the empty list returns true."
  (cond
   ((equal list-of-characters nil) t)
   ((not (member (car list-of-characters) capital-letters)) nil)
   (t (chars-are-capitalized (cdr list-of-characters)))))

(defun string-is-capitalized (string)
  "Returns true if every character in a string is a capital letter. The         
empty string returns true."
  (chars-are-capitalized (string-to-list string)))

它工作正常(尽管它依赖于我将只使用ASCII字符的假设),但我想知道我是否遗漏了一些我应该知道的明显的函数。

我不知道有什么内置函数可以满足您的需要,但这是:

(defun string-all-caps-p (string)
  "Return non-nil iff STRING is all capital letters."
  (save-match-data
    (let ((case-fold-search nil))
      (string-match "\\`[A-Z]+\\'" string))))
编辑:根据的反馈更改为使用“和”

这一个允许使用非A-Z字符(不是您要求的,但可能很有趣):


这只是一个粗略的猜测,但是如果你复制一个字符串,将其大写(我对lisp不太了解,但是快速的谷歌搜索告诉你有一个“大写”函数,然后检查这两个字符串是否相同?如果是,那么原始字符串必须全部大写:p

,参考其他答案:

  • 使用
    upcase
    不是一个好主意:它将分配一个新字符串,它不会发现该字符串是否包含非字母字符(似乎您想禁止这样做),并且它也适用于整数(Emacs将其用于字符)

  • 使用
    string-match
    更好——它解决了所有这些问题。正如Trey所示,当
    case-fold-search
    nil
    时,您需要这样做,否则Emacs可能会将其视为不区分大小写的搜索。但是
    string-match-p
    更好,因为它避免了更改匹配数据。(Emacs会在任何匹配后保留该数据,如果使用
    字符串匹配
    ,则会覆盖该数据,这可能会破坏使用函数的代码。)

  • 另一个问题是regexp本身。使用
    “^…$”
    意味着Emacs将查找具有匹配内容的某行——如果字符串具有换行符,这可能会使其返回虚假结果。您需要使用反斜杠unquote和反斜杠quote,它们只匹配字符串的开头和结尾

  • 因此,正确的版本是:

    (defun string-is-capitalized (str)
      (let ((case-fold-search nil))
        (string-match-p "\\`[A-Z]*\\'" str)))
    

    (顺便说一句,Emacs Lisp中的通常惯例是对谓词使用
    -p
    ,如
    字符串大写-p

    外部字符串操作库具有:

    它是这样实现的:

    (defun s-uppercase? (s)
      (let ((case-fold-search nil))
        (not (string-match-p "[[:lower:]]" s))))
    
    [:lower:]
    是对应于小写字符的。接受正则表达式并返回一个索引,从该正则表达式开始匹配,或者如果不匹配,则返回
    nil
    。其思想是在字符串中搜索小写字符,如果未找到,则返回
    t
    。但是
    string-match-p
    忽略大小写t、 因此,您应该暂时关闭


    Emacs默认使用,因此您可以在
    let
    表达式中临时将全局变量设置为不同的值。如果您将绑定设置为词法,let将引入
    case fold search
    的本地副本,隐藏全局变量,因此上面的代码将无法工作。

    第一个是有意义的;我应该认为我已经考虑过检查(相等字符串(upcase字符串)),但如果字符串中有任何非字母,我确实需要它返回false。对于第一个,您可能希望将其包装在
    save match data
    调用中,这样任何现有的正则表达式匹配数据都不会被覆盖。而不是
    a-Z
    我认为您希望在正则表达式中使用
    [:upper://code>。嗯,(1)我不喜欢
    [:upper:
    因为它往往意味着不同的东西(有些是unicode大写字符,有些是A-Z),所以我尽可能喜欢更明确的形式;(2)我回答了最初提出的问题,代码仅限于
    A-Z
    ;(3)regexp的使用已经足够好了,所以随机旁路器在需要时自然会使用其他东西;(4)最后,请注意,我使用了“正确的版本”并避免了对regexp的讨论,以使其更加集中…这为我澄清了一个主要的困惑点,谢谢。一个次要的评论:在我的系统中,此函数可以工作,而不管函数的范围是词汇范围还是动态范围。我想知道
    case fold search
    是否是一个所谓的特殊变量,这意味着它将要动态绑定的tinue。(有关详细信息,请参阅。)
    (s-uppercase "GOT TO. THIS AMERICA, MAN.") ; t
    (s-uppercase "You cannot lose if you do not play.") ; nil
    
    (defun s-uppercase? (s)
      (let ((case-fold-search nil))
        (not (string-match-p "[[:lower:]]" s))))