Skip to content

LISP - 字符串搜索

文本处理是软件开发中的常见任务。Common Lisp 提供了强大的内置工具用于简单的子字符串(substring)搜索,并且可以通过库(libraries)扩展,以实现基于正则表达式(regular expressions,简称 regex)的高级模式匹配。

使用 search 进行基本子字符串搜索

Section titled “使用 search 进行基本子字符串搜索”

用于在一个序列中查找另一个序列的主要函数是 search。当用于字符串时,它会查找一个子字符串。它返回第一个匹配项的起始索引(index),如果没有找到匹配项,则返回 NIL。

示例:区分大小写和不区分大小写的搜索

Section titled “示例:区分大小写和不区分大小写的搜索”
(let ((main-string "Welcome to the Lisp tutorial!"))
(format t "Main String: '~a'~%~%" main-string)
;; 1. 成功的区分大小写搜索
(format t "Searching for \"Lisp\": ~a~%"
(search "Lisp" main-string))
;; 2. 失败的区分大小写搜索
(format t "Searching for \"lisp\": ~a~%"
(search "lisp" main-string))
;; 3. 使用 :test 进行成功的、不区分大小写的搜索
(format t "Searching for \"lisp\" (case-insensitive): ~a~%"
(search "lisp" main-string :test #'string-equal))
;; 4. 搜索不存在的子字符串
(format t "Searching for \"Java\": ~a~%"
(search "Java" main-string)))
Main String: 'Welcome to the Lisp tutorial!'
Searching for "Lisp": 15
Searching for "lisp": NIL
Searching for "lisp" (case-insensitive): 15
Searching for "Java": NIL

实现不区分大小写的关键是 :test 关键字参数。通过提供 #'string-equal,我们告诉 search 使用不区分大小写的比较函数,而不是默认的 #'eql。

使用正则表达式进行高级模式匹配

Section titled “使用正则表达式进行高级模式匹配”

对于比简单子字符串更复杂的任何情况,行业标准是使用 正则表达式 (regex)。虽然它并非 ANSI Common Lisp 标准的内置部分,但一个名为 cl-ppcre 的强大库被广泛使用。

要使用它,首先你需要一个安装了 Quicklisp 包管理器(package manager)的现代 Lisp 环境。然后你可以通过以下方式加载该库:

;; 在你的 Lisp REPL 中
(ql:quickload "cl-ppcre")

想象一下,你想要在一个大段文本中找到一个电子邮件地址。这正是正则表达式的完美应用场景。

;; 确保你已首先加载 cl-ppcre
(defpackage #:my-regex-example
(:use #:cl #:cl-ppcre))
(in-package #:my-regex-example)
(let ((text "Contact us at support@example.com for help."))
(format t "Text: '~a'~%" text)
;; 用于匹配简单电子邮件地址的正则表达式
(let ((email-regex "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"))
;; scan-to-strings 返回匹配到的字符串作为结果
(multiple-value-bind (match registers)
(scan-to-strings email-regex text)
(declare (ignore registers))
(if match
(format t "Found email address: ~a~%" match)
(format t "No email address found.~%")))))
Text: 'Contact us at support@example.com for help.'
Found email address: support@example.com
  • 何时使用 search… 当你需要查找一个固定的、字面意义的子字符串时。它简单、快速且是内置功能。
  • 何时使用像 cl-ppcre 这样的正则表达式库… 当你需要查找模式(如电子邮件、URL、日期)、验证输入格式或执行复杂的搜索替换操作时。