所有。我想知道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字符的假设),但我想知道我是否遗漏了一些我应该知道的明显功能。
答案 0 :(得分:12)
参考其他答案:
使用upcase
是不一个好主意:它将分配一个新字符串,如果该字符串具有非字母字符,它将无法找到(似乎您想要禁止那个),它也适用于整数(Emacs用于字符)。
使用string-match
更好 - 它解决了所有这些问题。正如Trey所示,当case-fold-search
为nil
时,您需要这样做,否则Emacs可能会将其视为不区分大小写的搜索。但是string-match-p
更好,因为它避免了更改匹配数据。 (Emacs会在任何匹配后保留该数据,如果您使用string-match
,则会覆盖它,这可能会破坏使用您的函数的代码。)
另一个问题是regexp本身。使用"^...$"
意味着Emacs将查找具有匹配内容的某些行 - 如果您的字符串具有换行符,则可能使其返回虚假结果。你需要使用反斜杠 - unquote和反斜杠引用,它们只匹配字符串的开头和结尾。
所以正确的版本是:
(defun string-is-capitalized (str)
(let ((case-fold-search nil))
(string-match-p "\\`[A-Z]*\\'" str)))
(顺便说一下,Emacs Lisp中的通常惯例是使用-p
作为谓词,如string-capitalized-p
中所述。)
答案 1 :(得分:7)
我不知道你做了什么的内置函数,但是这样做:
(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))))
编辑:根据Eli Barzilay的反馈更改为使用`和'。
这个让非A-Z字符(不是你要求的,但也许有趣):
(defun string-has-no-lowercase (string)
"Return true iff STRING has no lowercase"
(equal (upcase string) string))
答案 2 :(得分:4)
外部字符串操作库s.el
有s-uppercase?
:
(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))))
[[:lower:]]
是对应于小写字符的Emacs-specific regex。 string-match-p
接受正则表达式并返回正则表达式匹配的索引,如果没有匹配则返回nil
。我们的想法是在字符串中搜索小写字符,如果没有找到,则返回t
。但是string-match-p
默认情况下会忽略大小写,因此您应该暂时关闭case-fold-search
。
默认情况下,Emacs使用dynamic binding,因此您可以临时将全局变量设置为let
表达式中的不同值。如果你设置绑定到lexical,我们会引入case-fold-search
的本地副本,遮蔽全局变量,因此上面的代码不起作用。
答案 3 :(得分:0)
只是一个疯狂的猜测,但是如果你制作一个字符串的副本,就可以了解它(我真的不太了解lisp但是快速谷歌搜索告诉它有一个“upcase”函数,然后检查两个字符串是相同的吗?如果是,那么原始的必须是所有的优势:P