【问题标题】:Check if a string ends with a suffix in Emacs Lisp检查字符串是否以 Emacs Lisp 中的后缀结尾
【发布时间】:2014-04-19 16:05:38
【问题描述】:

是否有一个函数可以检查字符串是否以某个子字符串结尾? Python有endswith:

>>> "victory".endswith("tory")
True

【问题讨论】:

    标签: string emacs elisp substring string-matching


    【解决方案1】:

    只需安装s.el 字符串操作库并使用它的s-suffix? 谓词:

    (s-suffix? "turn." "...when it ain't your turn.") ; => t
    

    但是如果你拒绝使用这个库,你必须编写自己的函数。在subr.el 中有string-prefix-p,它类似于Python 的str.startswith,它只是compare-strings 的包装。根据Emacs 24.3 changelog

    ** New function `string-prefix-p'.
    (This was actually added in Emacs 23.2 but was not advertised at the time.)
    

    string-suffix-padded only in Emacs 24.4,所以对于早期版本,我写道:

    (defun string-suffix-p (str1 str2 &optional ignore-case)
      (let ((begin2 (- (length str2) (length str1)))
            (end2 (length str2)))
        (when (< begin2 0) (setq begin2 0))
        (eq t (compare-strings str1 nil nil
                               str2 begin2 end2
                               ignore-case))))
    

    (when (&lt; begin2 0) (setq begin2 0)) 是一种解决方法,因为如果您将负数传递给compare-strings,它会与*** Eval error *** Wrong type argument: wholenump, -1 发生冲突。

    如果你对函数进行字节编译,它比yves Baumes 解决方案运行得更快,即使string-match 是一个C 函数。

    ELISP> (setq str1 "miss."
                 str2 "Ayo, lesson here, Bey. You come at the king, you best not miss.")
    ELISP> (benchmark-run 1000000 (string-suffix-p str1 str2))
    (4.697675135000001 31 2.789847821000066)
    ELISP> (byte-compile 'string-suffix-p)
    ELISP> (benchmark-run 1000000 (string-suffix-p str1 str2))
    (0.43636462600000003 0 0.0)
    ELISP> (benchmark-run 1000000 (string-match "miss\.$" str2))
    (1.3447664240000001 0 0.0)
    

    【讨论】:

    • compare-strings 也是在 C 中实现的,很可能是一个简单的逐字节内存比较,而 string-match 需要编译并运行 RE 状态机进行测试。不出所料,这要慢几个数量级。
    【解决方案2】:

    您可以在调用string-match 函数时使用正则表达式。

    (if (string-match-p "tory\\'" "victory")
        (message "victory ends with tory.")
       (message "victory does not ends with tory."))
    

    【讨论】:

    • 你没有转义点,所以在这个版本中它匹配 txt 之前的任何字符,而不仅仅是一个点(例如它也匹配 footxt
    • -1: $ 匹配的结尾。您必须使用\\' 来匹配字符串的结尾。
    • 另外,您应该使用string-match-p 来保留match-data
    • @lunaryorn 同样(string-match "\\.txt$" "foo.txtAAA") 返回 nil,这是预期的结果。请问有反例吗?
    • @yvesBaumes (string-match "\\.txt$" "foo.txt\nAAA")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-23
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多