Проверить, все ли заглавные буквы в Emacs lisp? - PullRequest
5 голосов
/ 25 января 2010

все. Мне было интересно, есть ли в 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), но мне было интересно, не упустил ли я какую-то очевидную функцию, о которой мне следует знать.

Ответы [ 4 ]

12 голосов
/ 25 января 2010

Применительно к другим ответам:

  1. Использование upcase - это , а не хорошая идея: он будет выделять новую строку, он не найдет, если строка содержит не алфавитные символы (кажется, что вы хотите запретить ) и работает также с целыми числами (которые Emacs использует для символов).

  2. Использование string-match лучше - это устраняет все эти проблемы. Как показывает Трей, это нужно сделать, когда case-fold-search равен nil, иначе Emacs может рассматривать его как поиск без учета регистра. Но string-match-p еще лучше, поскольку он позволяет избежать изменения данных о совпадении. (Emacs сохраняет эти данные после любого совпадения, и если вы используете string-match, вы перезапишете их, что может привести к нарушению кода, использующего вашу функцию.)

  3. Другой проблемой является само регулярное выражение. Использование "^...$" означает, что Emacs будет искать какую-то строку с соответствующим содержимым - и если ваша строка содержит символы новой строки, это может заставить ее выдать поддельный результат. Вам необходимо использовать обратную косую черту и обратную косую черту, которые соответствуют только началу и концу строки.

Итак, правильная версия:

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

(Кстати, в Emacs Lisp принято использовать -p для предикатов, как в string-capitalized-p.)

7 голосов
/ 25 января 2010

Я не знаю встроенной функции, которая делает то, что вы хотите, но это делает:

(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))
4 голосов
/ 06 января 2015

Библиотека внешних манипуляций со строками 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 , соответствующее строчному символу. string-match-p принимает регулярное выражение и возвращает индекс, начиная с которого сопоставляется регулярное выражение, или возвращает nil, если совпадения нет. Идея состоит в том, чтобы искать строчные символы в строке, и если ничего не найдено, вернуть t. Однако string-match-p игнорирует регистр по умолчанию, поэтому вам следует временно отключить case-fold-search.

Emacs по умолчанию использует динамическое связывание , поэтому вы можете временно устанавливать глобальные переменные в различные значения внутри выражения let. Если вы установите привязку к лексическому, пусть введет локальную копию case-fold-search, скрывая глобальную переменную, поэтому приведенный выше код не будет работать.

0 голосов
/ 25 января 2010

просто дикая догадка, но что, если вы сделаете копию строки, поставьте ее в верхний регистр (я действительно не очень разбираюсь в lisp, но быстрый поиск в Google показал, что есть функция "upcase", а затем проверьте, есть ли две строки одинаковы? Если есть, то оригинал должен быть в верхнем регистре: P

...