`

Programming in Emacs Lisp笔记(十二)正则表达式查询

阅读更多

正则表达式查询

在Emacs中正则表达式查询使用得很广泛。在forward-sentence和forward-paragraph中使用了正则表达式查找定位。正则表达式'regular expression'常被写作'regexp'。

sentence-end的正则表达式

符号sentence-end被绑定到匹配名末的正则式上。

句末通常是用一个句号、问号或者叹号结束的。那么这个正则表达式应该包含下面的字符:

[.?!]
然而,在有些时候句号、问号或叹号也有可能在某个语句的中间,我们并不想在使用forward-sentence的时候跳转到这些符号上去。

习惯上,你可能会在每个句子后面添加空格或者tab等等。我们可以用下面的表达式来匹配:

\\($\\| \\|  \\)
^ ^^
TAB SPC
$标明行末,括号前面的两个反斜线和竖线前面的两个反斜线中第一个反斜线是转义符。

语句的结束位置也可能跟了一个或者多个回车,如下:

[
]*
星号表明可以有零个或者多个回车。

一个语句的结束位置可能不只是句号、问号或叹号。它也可能是:一个回括号或其它:

[]\"')}]*
在这个表达式中,第一个]是表达式的第一个字符;第二个字符是",综前面加了一个转义符。最后三个字符是',),}

前面的表达式都是用于匹配一个语句的,如果我们对sentence-end求值,将返回下面的结果:

sentence-end
=> "[.?!][]\"')}]*\\($\\| \\| \\)[
]*"

re-search-forward函数

re-search-forward函数与search-forward函数很相似。

re-search-forward函数搜索一个正则表达式。如果查找成功,它将point设置在匹配目标的最后一个字符的后面。如果是向后查找,它将point设置在匹配目标的第一个字符的前面。

与search-forward一样,re-search-forward函数接收四个参数:

  1. 第一个参数是要查找的正则表达式。表达式是一个被引号包括的字符串。
  2. 第二个参数是可选参数,限制搜索的范围,它是当前缓冲区中的某个位置(point)。
  3. 第二个可选参数指定搜索失败时如何处理:如果第三个参数为nil,则导致函数在搜索失败时显示错误信息;其它值将使函数失败时返回nil,搜索成功时返回t。
  4. 可选参数,用于指定重复次数。负数表示重复的向后搜索。

re-search-forward使用模板如下:

(re-search-forward "regular-expression"
limit-of-search
what-to-do-if-search-fails
repeat-count)
第二、三、四个参数是可选的。如果你想传递给最后两个参数,则必须也给前面的参数全传值。否则解释器将出错。

在forward-sentence函数中,sentence-end正则表达式如下:

"[.?!][]\"')}]*\\($\\|  \\|  \\)[
]*"
这限制了查询范围只到当前段落的结束位置(一个句子不可能超过段落)。如果查询失败,函数将返回nil;查询的次数可以由传递给forward-sentence函数的参数来提供。

forward-sentence函数

这个命令将光标移到下一句,是在Emacs Lisp中使用正则表达式的很好的例子。实际这个函数看起来很长很复杂;这是因为函数被设计为能向前也能向后移动。该函数通常被绑定到M-e上。

forward-sentence了函数定义

(defun forward-sentence (&optional arg)
"Move forward to next sentence-end. With argument, repeat.
With negative argument, move backward repeatedly to sentence-beginning.
Sentence ends are identified by the value of sentence-end
treated as a regular expression. Also, every paragraph boundary
terminates sentences as well."

(interactive "p")
(or arg (setq arg 1))
(while (< arg 0)
(let ((par-beg
(save-excursion (start-of-paragraph-text) (point))))
(if (re-search-backward
(concat sentence-end "[^ \t\n]") par-beg t)
(goto-char (1- (match-end 0)))
(goto-char par-beg)))
(setq arg (1+ arg)))
(while (> arg 0)
(let ((par-end
(save-excursion (end-of-paragraph-text) (point))))
(if (re-search-forward sentence-end par-end t)
(skip-chars-backward " \t\n")
(goto-char par-end)))
(setq arg (1- arg))))

这个函数看起来太长了,最好是先弄清楚它的骨架,然后再了解细节。我们先从最左边开始看:

(defun forward-sentence (&optional arg)
"documentation..."
(interactive "p")
(or arg (setq arg 1))
(while (< arg 0)
body-of-while-loop
(while (> arg 0)
body-of-while-loop
这样看起来简单多了。函数定义由文档字符串,一个interactive语句,一个or语句和while循环组成。

依次来看看各个部分。

文档简单易懂。

interactive函数有一个"p"参数。这表示处理前缀参(C-u)。如果没有传递这个参数将被设置为1。如果在调用forward-sentence时,不是使用的交互式模式并且没有带参数,arg将被设置为nil。

while循环部分

or语句后面有两个while循环。第一个while循环的true-or-false-test测试前缀参数是否为负数。这决定是否向后查询。循环体与第二个while的循环体类似,但不完全相同。我们跳过第一个while循环,集中看第二个循环

第二个循环将向前移动point。代码骨架如下:

(while (> arg 0)            ; true-or-false-test
(let varlist
(if (true-or-false-test)
then-part
else-part
(setq arg (1- arg)))) ; while loop decrementer
这个while循环是一个递减循环。它的true-or-false-test检查计数器(arg)是否大于0;并每次循环中将计数器减1。

如果没有前缀参数传递给forward-sentence,arg将被设置为1,while循环将只运行一次。

while循环体如下:

(let ((par-end
(save-excursion (end-of-paragraph-text) (point))))
(if (re-search-forward sentence-end par-end t)
(skip-chars-backward " \t\n")
(goto-char par-end)))
let语句创建了一个局部变量par-end。前面我们看过,这局部变量用于限制正则表达式搜索的范围。如果它没有找到段落中的语句的结束位置,它将段落结束位置前停止搜索。

首先,我们来研究一下par-end是如何被绑定到段落结束位置的。程序使用了let语句将下面语句的结果赋给了par-end变量。

(save-excursion (end-of-paragraph-text) (point))
在这个语句中,(end-of-paragraph-text)将point移动到段落的结束位置,(point)返回当前的point,然后用save -excursion恢复point到原来的位置。因此,let将par-end绑定到了save-excursion的返回值,即段落的结束位置。 ((end-of-paragraph-text)函数使用了forward-paragraph函数)

接下来Emacs继续执行let的body部分,一个if语句:

(if (re-search-forward sentence-end par-end t) ; if-part
(skip-chars-backward " \t\n") ; then-part
(goto-char par-end))) ; else-part

正则表达式查询

re-search-forward函数根据sentence-end定义的正则表达式查找名末。如果找到,re-search-forward函数将做两件事:

  1. re-search-forward函数将point移到找到的目标的结束位置。
  2. re-search-forward函数返回true。这个值被if接收,表明查找成功。

当查找成功后,if语句执行then部分,这部分表达式(skip-chars-backward "\t\n")这个语句向后移过任何空白字符直到遇到一个可打印字符,然后把point设置在这个字符的后面。

如果re-search-forward函数找不到句末位置,则函数返回false。false将使if语句执行它的第三个参数,(goto-char par-end):它将point移到段落末尾。

forward-paragraph函数

forward-paragraph函数将point移到段落结束位置。通常被绑定到M-}上,它使用了大量重要的函数,包括:let*,match-beginning和looking-at。

forward-paragraph函数定义比forward-sentence的长很多,因为它工作于段落上,段落的每行可能以是填充前缀开头。

填充前缀是放在行的开头,通常是由一些重复的字符组成的字符串。比如,在Lisp代码中通常在一大段注释的每行前面添加;;;。在文本模式下(Text mode),四个空格标明了一个段落的缩进。

这意味着在查找段落时,需要查找那些最左边的列有填充前缀的行。

有些情况下需要忽略这些前缀,特别是在使用空行来分隔段落时。这更增加了这个函数的复杂性。

forward-paragraph函数定义的骨架

(defun forward-paragraph (&optional arg)
"documentation..."
(interactive "p")
(or arg (setq arg 1))
(let*
varlist
(while (< arg 0) ; backward-moving-code
...
(setq arg (1+ arg)))
(while (> arg 0) ; forward-moving-code
...
(setq arg (1- arg)))))
第一部分是常见部分:参数列表,包含一个可选参数。而后是文档字符串。

interactive的参数p表示可以处理前缀参数(C-u)。这是一个数字,用于设置执行的次数。or语句处理没有传递参数时的情况。

let*语句

符号let*不是let。

let*与let类似,不同之处在于Emacs将依次给各个变量赋值,给后面的变量赋值语句可以使用前面已经赋值的变量。

在这个let*语句中,Emacs设置了两个变量:fill-prefix-regexp和paragraph-separate。变量fill-paragraph-separate的值,依赖于fill-prefix-regexp的值。

依次来看,符号fill-prefix-regexp的值被设置为下面的list的返回值:

(and fill-prefix
(not (equal fill-prefix ""))
(not paragraph-ignore-fill-prefix)
(regexp-quote fill-prefix))
在前面学习kill-new函数时,我们知道and将执行传递给它的每个参数直到有一个参数的返回值为nil,这种情况下and语句返回nil;如果没有参数返回nil,and语句将返回最后一个参数的值。简单来说,and语句在所有参数都为true时返回true。

变量fill-prefix-regexp只有在上面四个语句都为true时,才会设置为一个非nil值,否则fill-prefix-regexp将被设置为nil。

fill-prefix
当这个变量被执行时,如果没有填充前缀,变量返回nil。
(not (equal fill-prefix "")
这个语句检查填充字符串是否为一个空字符串。
(not paragraph-ignore-fill-prefix)
如果paragraph-ignore-fill-prefix设了值(比如t),这个表达式将返回nil。
(regexp-quote fill-prefix)
这是and语句的最后一个语句。如果and中所有的语句都为true,这条语句的返回值将作为and语句的返回值,这个返回值被设置到变量fill-prefix-regexp。

and语句的将fill-prefix-regexp设置为被regexp-quote函数修改过的fill-prefix上。regexp- quote函数读取一个字符串并返回能精确匹配这个字符串的正则表达式。这意味着fill-prefix-regexp将被设置为通匹配填充前缀的正则表 达式。

let*语句设置的第二个局部变量是paragraph-separate。它被设置为下面语句的返回值:

(if fill-prefix-regexp
(concat paragraph-separate
"\\|^" fill-prefix-regexp "[ \t]*$")
paragraph-separate)))
这个语句显示了let*与let的区别。if语句的true-or-false-test检查fill-prefix-regexp是否为nil。

如果fill-prefix-regexp没有值,Emacs将执行if语句的else部分,将paragraph-separate设置为它的原始值。(paragraph-separate是一个匹配段落分隔的正则表达式)

如果fill-prefix-regexp有值,Emacs将执行if语句的then部分并将paragraph-separate设置为包含fill-prefix-regepx的正则表达式。

特别的是,paragraph-separate被设置为由它的原始值与fill-prefix-regexp组成的新值上。^表示fill-prefix-regexp必须在行首,行末可以是空白字符,这由"[ \t]*$"来定义。\\|表示"或"关系。

接下来进入let*语句的body部分。let*语句的第一部分处理给定的参数为负数,需要向后移动的情况。我们跳过这一部分。

while循环中的向前移动

let*的body的第二部分处理向前移动。由于个while循环执行arg参数指定的循环次数。通常情况下参数被设置为1,循环只执行一次,光标向前移动一个段落。

这个部分共处理了三种情况:当point在段落中间时,当point在有填充前缀的段落内部时,当point在没有段落前缀的段落内部时。

while循环部分如下:

(while (> arg 0)
(beginning-of-line)

;; between paragraphs
(while (prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1)))

;; within paragraphs, with a fill prefix
(if fill-prefix-regexp
;; There is a fill prefix; it overrides paragraph-start.
(while (and (not (eobp))
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))

;; within paragraphs, no fill prefix
(if (re-search-forward paragraph-start nil t)
(goto-char (match-beginning 0))
(goto-char (point-max))))

(setq arg (1- arg)))
我们马上就可以看出这是一个递减的while循环,使用了(setq arg (1- arg))作为递减语句。

循环体包含了三个语句:

;; between paragraphs
(beginning-of-line)
(while
body-of-while)

;; within paragraphs, with fill prefix
(if true-or-false-test
then-part

;; within paragraphs, no fill prefix
else-part
当解释器执行while循环体时,第一件事就是执行(begion-of-line)语句将point移到行首位置。接下来是一个内部的while循环。这个while循环被设计为将光标从段落间的空白部分移出。最后是一个if语句将point移到段落的结束位置。

段落之间

首先,我们来看内部的while循环。这个循环处理point位于段落之间的情况;它使用了三个新的函数:prog1, eobp 和 looking-at。

  • prog1与progn类似,但是progn1返回的是它的第一个参数的值。(progn返回它的最后一个参数的值)后面的语句也将被执行。
  • eobp是End Of Buffer P的缩写,检查point是否在缓冲区的结束位置。
  • looking-at函数检查point后面的文本是否与传递给它的正则表达式参数匹配。

这个while循环部分如下:

(while (prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1)))
这是一个没有循环体的while循环!true-or-false-test部分如下:
(prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1))
prog1的第一个参数是一个and语句。它检查point是否到了缓冲区的结束位置,也检查point后面的文本是否与正则表达式paragraph-separate匹配。

如果光标不在缓冲区结束位置且光标后面的文本是一个段落分隔,则and语句返回true。执行完and语句后,解释器执行prog1的第二个参数 forward-line。它将光标向前移动一行。由于prog1的返回值是它的第一个参数,因此while循环将在point不在缓冲区结束位置或位于 段落之间时继续执行。最后,point将在and语句测试为false时被移到一个新段落,由于这时forward-line已经被执行了。这意味着 point已经从段落之间的位置移到了段落中,它停留在新段落第二行的开始位置。

段落内部

外部while循环的第二个部分是一个if语句。解释器将在fill-prefix-regexp不为nil时执行它的then部分,如果fill-prefix-regexp为nil,它将执行else部分(当段落没有填充前缀时)。

没有填充前缀

代码包含了一个if语句:

(if (re-search-forward paragraph-start nil t)
(goto-char (match-beginning 0))
(goto-char (point-max)))
它查找一个正则表达式,直到下一个段落的开始位置,如果找到,就将point设置到那时在,如果下一个段落的开始位置未找到,则将point移到当前缓冲区可访问区域的结束位置。

这段代码里只有match-beginning比较陌生。它返回一个数字,这个数字标明了上一个正则表达式所匹配位置。

在这里使用match-beginning函数是由于forward search的一个特性:forward search查找成功时不管理普通查找还是正则表达式查找,它都会将point移到查找到的文本的结束位置。在这里,这样操作将使point移动到下一个 段落的开始位置,而不是当前段落的结束位置。而这两个位置可能是不同的,因为段落之间可能有空行

当传的参数为0时,match-beginning函数返回的位置是最近一次匹配正则表达式的文本的开始位置。在这里,最近一次使用正则表达式查找 的就是paragraph-start,因此match-begnning返回匹配的开始位置,而不是匹配的结束位置。这个开始位置即段落的结束位置。

有填充前缀时的情况

前面讨论了if语句的else部分。如果if语句检测到有填充前缀,它将执行then部分:

(while (and (not (eobp))
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))
当下面三个条件都为true时,它将point向前移动一行:
  1. point不是位于缓冲区结束位置
  2. point后面的文本不是段落分隔符
  3. point后面的文本与填充前缀的正则表达式匹配

小结

在向前移动时,forward-paragraph函数执行了下面三个操作:

  • 将point移到行首
  • 忽略段落之间的行
  • 检查是否有填充前缀,如果有:
    • 向前移动一行直到该行不为段落分隔行
  • 如果没有填充前缀:
    • 查找下个段落的开始位置
    • 转到下个段落的开始位置,也就是前一个段落的结束位置
    • 或者转到缓冲区的结束的位置

下面是格式化过的代码:

(interactive "p")
(or arg (setq arg 1))
(let* (
(fill-prefix-regexp
(and fill-prefix (not (equal fill-prefix ""))
(not paragraph-ignore-fill-prefix)
(regexp-quote fill-prefix)))

(paragraph-separate
(if fill-prefix-regexp
(concat paragraph-separate
"\\|^"
fill-prefix-regexp
"[ \t]*$")
paragraph-separate)))

omitted-backward-moving-code ...

(while (> arg 0) ; forward-moving-code
(beginning-of-line)

(while (prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1)))

(if fill-prefix-regexp
(while (and (not (eobp)) ; then-part
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))
; else-part: the inner-if
(if (re-search-forward paragraph-start nil t)
(goto-char (match-beginning 0))
(goto-char (point-max))))

(setq arg (1- arg))))) ; decrementer
完整的代码不光有向前移动的代码,也包括了向后移动的代码。

在Emacs中可以用C-h f(describe-function)和函数名来查看整个函数。

可以使用M-.(find-tag)并输入函数名来查找函数定义。

创建自己的TAGS文件

M-.命令可以查看函数源码,变量或其它的源码。这个函数依赖于tags表告诉他该到哪里查找源码。

经常会需要自己创建tags表。tags表被称为TAGS文件。

可以用Emacs发行版中的etags程序来创建TAGS文件。通常etags不是Emacs Lisp函数,而是一个C程序。

创建TAGS文件前,先进入要创建这个文件的目录。在Emacs中可以用M-x cd命令,或者直接访问某个目录C-x d(dired)。然后运行编译命令并执行etags .el。

M-x compile RET etags .el RET
etags命令支持通配符。如果你有两个目录,你可以使用一个TAGS文件,输入*.el ../elisp/*.el,在这里../elisp/是第二个目录:
M-x compile RET etags *.el ../elisp/*.el RET
输入
M-x compile RET etags --help RET
查看etags支持的选项列表。

etags程序支持20多种语言,包括:Emacs Lisp、Common Lisp、Scheme、C、C++、Ada、Fortran、Java、Latex、Pascal、Perl、Python、Texinfo、 makefiles等等。程序没有开关指定语言;它会根据输入的文件名和文件内容来识别语言的种类。

使用:M-x locate RET TAGS RETEmacs将列出你的所有TAGS文件的完整路径。

如果你想访问你创建的TAGS文件,可以使用M-x visit-tags-table命令。

创建Emacs源码的TAGS文件

GNU Emacs的源码中的Makefile文件包含了复杂的etags命令,它创建,合并所有Emacs源码中的tags放到src顶层目录中的一个TAGS文件中。

你可以在Emacs源码的顶层目录中执行下面的命令来创建TAGS文件:

M-x compile RET make tags RET

回顾

  • while 循环执行直到传递给它的第一个参数为true。然后返回nil。 例:
(let ((foo 2))
(while (> foo 0)
(insert (format "foo is %d.\n" foo))
(setq foo (1- foo))))

=> foo is 2.
foo is 1.
nil
(insert函数插入它的参数到point所在的位置;format函数格式化它的参数;\n产生新行。 )
  • re-search-forward

查找一个正则表达式,如果找到了就将point设置到目标位置的后面。

与search-forward类似,它接收四个参数:

  1. 要查找的正则表达式
  2. 可选参数,限制查询范围
  3. 可选参数,查找失败时如何处理,返回nil或者显示错误信息
  4. 可选参数,查找的重复数次;如果为负数,则向后查找
  • let*

将变量值绑定到各个变量上,并执行其它的参数,返回最后一个的值。在设置变量时,可以使用前面已经设置过的局部变量。

例:

(let* ((foo 7)
(bar (* 3 foo)))
(message "`bar' is %d." bar))
=> `bar' is 21.
  • match-beginning

返回上一次正则表达式查找时查找的文本的开始位置。

  • looking-at

如果point后面的文本与函数的参数(是一个正则表达式)匹配则返回t。

  • eobp

如果point在可访问的缓冲区的结束位置则返回t。如果缓冲区未被narrowed,则可访问缓冲区结束位置是缓冲区的结束位置。如果缓冲区被narrowed,则结束位置为narrowed部分的结束位置。

  • prog1

依次执行各个参数并返回第一个参数的值。

例:

(prog1 1 2 3 4)
=> 1
评论

相关推荐

    An Introduction to Programming in Emacs Lisp

    - **标题**:“An Introduction to Programming in Emacs Lisp”(Emacs Lisp编程入门) - **描述**:该资源是基于Emacs官方文档的重编版本,旨在提供更易阅读的字体样式。 #### 知识点详解 ##### 1. Emacs Lisp...

    Programming in Emacs Lisp

    Programming in Emacs Lisp英文版

    An Introduction to Programming in Emacs Lisp Second Edition

    - **标题**:“An Introduction to Programming in Emacs Lisp Second Edition” - **描述**:本书是关于Emacs Lisp编程的入门教程,被誉为“经典中的经典”。 该书由Robert J. Chassell撰写,由自由软件基金会出版...

    Robert Chassell:An Introduction to Programming in Emacs Lisp

    ### Robert Chassell:An Introduction to Programming in Emacs Lisp #### 知识点概览 - **Lisp Lists**: 介绍Lisp列表的概念及其在Emacs Lisp中的应用。 - **Lisp Atoms**: 解释Lisp原子的基本概念以及它们在...

    精通正则表达式&正则表达式经典实例

    9. **实例应用**:正则表达式广泛应用于文本编辑器(如vim、emacs)、编程语言(如JavaScript、Python、Java)和搜索引擎(如grep、findstr)。例如,用于验证邮箱格式、手机号码、提取URL等。 通过《精通正则...

    Python正则表达式操作指南%2B-%2BUbuntu中文.pdf

    ### Python正则表达式操作指南知识点详解 #### 1. 简介 - **re模块**: Python自1.5版本起引入了`re`模块,该模块支持Perl风格的正则表达式模式。与之前的`regex`模块提供的Emacs风格相比,`re`模块更加功能强大且...

    正则表达式素材3

    正则表达式的概念始于文本编辑器,如vi和emacs,后来被广泛应用于各种编程语言和工具中,如Perl、Python、JavaScript、Java等。它们在数据验证、搜索替换、文件查找、网页爬虫等领域有着广泛的应用。 1. **基础概念...

    Python正则表达式操作指南.pdf

    早期版本则通过`regex`模块提供了Emacs风格的正则表达式支持。 - **优势**:与Emacs风格相比,Perl风格的正则表达式更加功能强大且易于阅读。 - **应用场景**: - **字符串匹配**:检查字符串是否符合某种模式。 ...

    JAVA 正则表达式

    正则表达式支持的工具众多,包括但不限于grep、awk、vi和Emacs文本编辑器。脚本语言如Python、Tcl、JavaScript和Perl也都支持正则表达式,其中Perl在文本处理方面的应用尤为出色。 在Java语言中,正则表达式的支持...

    An Introduction to Programming in Emacs Lisp [3.10].chm

    An Introduction to Programming in Emacs Lisp [3.10].chm

    精通正则表达式

    - 在文本编辑器(如vim、emacs)中,正则表达式常用于查找、替换和多行操作。 - 在Web开发中,正则表达式用于表单验证,确保用户输入的数据格式正确。 9. **效率优化** - 理解并避免回溯,合理使用贪婪与非贪婪...

    JAVA 正则表达式(超详细)

    1. 正则表达式的引擎:正则表达式的引擎已经被许多 Unix 工具实现,包括 grep、awk、vi 和 Emacs 等。许多脚本语言也支持正则表达式,例如 Python、Tcl、JavaScript 和 Perl。 2. Java 正则表达式的历史:Java 一直...

    正则表达式参考文档揭开正则表达式的神秘面纱

    - 文本编辑器:如Vim、Emacs等,提供了强大的正则表达式搜索和替换功能。 - 命令行工具:如Unix/Linux的grep、sed、awk等,利用正则表达式处理文本文件。 四、正则表达式实例 1. 验证邮箱格式:`/^[a-zA-Z0-9._%+-...

    正则表达式书籍

    11. **实际应用**:书中可能涵盖如何在各种编程语言(如Python、Java、JavaScript)中使用正则表达式,以及在文本编辑器(如vim、emacs)或命令行工具(如grep、sed)中的应用。 12. **调试与测试**:介绍如何使用...

    python 正则表达式

    早期版本的Python使用的是`regex`模块,该模块支持Emacs风格的正则表达式,但在Python 2.5之后已被完全移除。 #### 二、简单的模式 ##### 2.1 匹配字符 在正则表达式中,最基本的单元是单个字符的匹配。例如: - ...

    了解正则表达式[归纳].pdf

    在UNIX环境中,Emacs文本编辑器也是一个强大的工具,它提供了内置的正则表达式查找和替换功能,还可以在源代码或文档中高亮显示匹配的模式。 正则表达式虽然强大,但也因其灵活性和多样性而显得复杂。不同的实现...

    很详细的Python正则表达式操作指南(re使用)

    相比于早期版本中提供的Emacs风格的正则表达式,Perl风格的正则表达式不仅功能更加强大,而且更加易于阅读和理解。 #### 简单模式 正则表达式中最基本的元素是字符匹配。大多数情况下,字母和字符都与自身匹配。...

    Python正则表达式操作指南

    - **regex模块**:Python 1.5 之前的版本提供的 Emacs 风格的正则表达式模式,功能较少且可读性较差,新代码建议避免使用。 #### 2. 简单模式 ##### 2.1 字符匹配 - **普通字符匹配**:大多数字母和数字等普通...

Global site tag (gtag.js) - Google Analytics