Double Commander

2.14. 正则表达式语法

内容

1. 介绍
2. 简单匹配
3. 转义序列
4. 字符类
5. 元字符
5.1. 元字符 - 行分隔符
5.2. 元字符 - 预定义类
5.3. 元字符 - 词边界
5.4. 元字符 - 迭代器
5.5. 元字符 - 替代项
5.6. 元字符 - 子表达式
5.7. 元字符 - 反向引用
6. 断言(前瞻和后瞻断言)
7. 非捕获组
8. 原子组
9. Unicode类别
10. 修饰符

Double Commander使用Andrey Sorokin编写的免费库TRegExpr

大多数解释来自该库的帮助文件。

1. 介绍

正则表达式是一种广泛使用的指定文本搜索模式的方法。特殊字符(元字符)允许我们指定,例如,我们正在查找的特定字符串出现在行的开头或结尾,或者包含字符或字符组的n次出现。

Double Commander在以下功能中支持正则表达式:

TRegExp库支持两种操作模式:ANSI和Unicode。在文本文件中搜索时,Double Commander使用两者(取决于文件编码)。在按名称搜索时,使用Unicode。

2. 简单匹配

任何单个字符都匹配自身,除非它是一个具有下面描述的特殊含义的元字符。

一系列字符匹配目标字符串中的该系列字符,因此模式bluh将匹配目标字符串中的bluh

我们可以通过在元字符或转义序列前面加上反斜杠\来使它们被逐字解释,例如:元字符^匹配字符串开头,但\^匹配字符^\\匹配\等等。

以下是一些示例:

简单匹配示例
表达式结果
foobar
匹配字符串foobar
\^FooBarPtr
匹配^FooBarPtr

3. 转义序列

可以使用类似于C和Perl中使用的转义序列语法来指定字符:\n匹配换行符,\t匹配制表符等。

更一般地,\xnn,其中nn是一串十六进制数字,匹配ASCII值为nn的字符。

如果您需要宽(Unicode)字符代码,可以使用\x{nnnn},其中nnnn – 一个或多个十六进制数字。

转义序列
表达式结果
\xnn
ASCII代码为nn的字符
\x{nnnn}
ASCII代码为nnnn的字符(普通文本为一个字节,Unicode为两个字节)
\t
制表符(HT/TAB),与\x09相同
\n
换行符(NL/LF),与\x0a相同
\r
回车符(CR),与\x0d相同
\f
换页符(FF),与\x0c相同
\a
警报(铃声)(BEL),与\x07相同
\e
转义(ESC),与\x1b相同

以下是一些示例:

转义序列示例
表达式结果
foo\x20bar
匹配foo bar(注意中间的空格)
\tfoobar
匹配由制表符预定义的foobar

4. 字符类

您可以通过将字符列表括在[]中来指定字符类,这将匹配列表中的任何一个字符。

如果[后的第一个字符是^,则该类匹配列表中包含的任何字符。

在列表中,-字符用于指定范围,因此a-z表示从az的所有字符,包括在内。

如果您希望-本身成为类的成员,请将其放在列表的开头或结尾,或用反斜杠转义。

如果您希望使用],可以将其放在列表的开头或用反斜杠转义。

字符类
表达式结果
[-az]
匹配az-
[az-]
匹配az-
[a\-z]
匹配az-
[a-z]
匹配从az的所有26个小写字母
[\n-\x0D]
匹配任何\x10\x11\x12\x13
[\d-t]
匹配任何数字、-t
[]-a]
匹配从]a的任何字符

以下是一些示例:

字符类示例
表达式结果
foob[aeiou]r
查找字符串foobarfoober等,但不包括foobbrfoobcr等。
foob[^aeiou]r
查找字符串foobbrfoobcr等,但不包括foobarfoober等。

5. 元字符

元字符是正则表达式的精髓,是特殊字符。

有不同的元字符类型,如下所述。

5.1. 元字符 - 行分隔符

一些表达式有助于检测行分隔。

行分隔符
表达式结果
^
行首
$
行尾
\A
文本开头
\Z
文本结尾
.
行中任何字符

以下是一些示例:

行分隔符示例
表达式结果
^foobar
仅当字符串foobar在行首时匹配
foobar$
仅当字符串foobar在行尾时匹配
^foobar$
仅当字符串foobar是行中唯一字符串时匹配
foob.r
匹配像foobarfoobbrfoob1r等字符串

默认情况下,^元字符仅保证在输入字符串/文本的开头匹配,$元字符仅在末尾匹配。嵌入的行分隔符不会被^$匹配。

但是,您可能希望将字符串视为多行缓冲区,这样^将在字符串内的任何行分隔符后匹配,$将在任何行分隔符前匹配。您可以通过打开修饰符m来实现。

\A\Z就像^$一样,但当使用修饰符m时,它们不会多次匹配,而^$将在每个内部行分隔符处匹配。

默认情况下,.元字符匹配任何字符,但如果关闭修饰符s,则.不会匹配嵌入的行分隔符。

TRegExpr按照Unicode技术标准(技术标准#18)处理行分隔符:

请注意,^.*$(空行模式)不会在\x0D\x0A序列中匹配空字符串,但会在\x0A\x0D序列中匹配空字符串。

5.2. 元字符 - 预定义类

一些表达式有助于检测字符组。

预定义类
表达式结果
\w
字母数字字符(包括_),即[0-9A-Za-z_]
\W
非字母数字字符
\d
数字字符
\D
非数字字符
\s
任何空格字符(与[ \t\n\r\f]相同)
\S
非空格字符

您可以在自定义字符类中使用\w\d\s

以下是一些示例:

预定义类示例
表达式结果
foob\dr
匹配像foob1rfoob6r等字符串,但不包括foobarfoobbr
foob[\w\s]r
匹配像foobarfoob rfoobbr等字符串,但不包括foob=r

5.3. 元字符 - 词边界

词边界(\b)是在其一侧有\w而另一侧有\W的两个字符之间的位置(以任一顺序),将字符串开头和结尾的假想字符计为匹配\W

词边界
表达式结果
\b
匹配词边界
\B
匹配非词边界

5.4. 元字符 - 迭代器

正则表达式的任何项目都可以跟随另一种类型的元字符 – 迭代器。

使用这些元字符,您可以指定前一个字符、元字符或子表达式的出现次数。

迭代器
表达式结果
*
零次或多次("贪婪"),类似于{0,}
+
一次或多次("贪婪"),类似于{1,}
?
零次或一次("贪婪"),类似于{0,1}
{n}
恰好n次("贪婪")
{n,}
至少n次("贪婪")
{n,m}
至少n次但不超过m次("贪婪")
*?
零次或多次("非贪婪"),类似于{0,}?
+?
一次或多次("非贪婪"),类似于{1,}?
??
零次或一次("非贪婪"),类似于{0,1}?
{n}?
恰好n次("非贪婪")
{n,}?
至少n次("非贪婪")
{n,m}?
至少n次但不超过m次("非贪婪")

因此,形式为{n,m}的花括号中的数字指定匹配项目的最小次数n最大次数m

形式{n}等同于{n,n},恰好匹配n次。

形式{n,}匹配n次或更多次。

nm的大小没有限制,但大数字会减慢执行速度并消耗更多内存。

如果花括号出现在任何其他上下文中,它被视为普通字符。

以下是一些示例:

迭代器示例
表达式结果
foob.*r
匹配像foobarfoobalkjdflkj9rfoobr等字符串
foob.+r
匹配像foobarfoobalkjdflkj9r等字符串,但不包括foobr
foob.?r
匹配像foobarfoobbrfoobr等字符串,但不包括foobalkj9r
fooba{2}r
匹配字符串foobaar
fooba{2,}r
匹配像foobaarfoobaaarfoobaaaar等字符串
fooba{2,3}r
匹配像foobaarfoobaaar等字符串,但不包括foobaaaar

关于"贪婪性"的一点解释。

"贪婪"取尽可能多,"非贪婪"取尽可能少。

例如,b+b*应用于字符串abbbbc返回bbbbb+?返回bb*?返回空字符串,b{2,3}?返回bbb{2,3}返回bbb

您可以将所有迭代器切换到"非贪婪"模式(参见修饰符g)。

5.5. 元字符 - 替代项

您可以使用|分隔一系列替代项来为模式指定,因此fee|fie|foe将匹配目标字符串中的feefiefoef(e|i|o)e也是如此)。

第一个替代项包括从上一个模式分隔符(([或模式开头)到第一个|的所有内容,最后一个替代项包含从最后一个|到下一个模式分隔符的所有内容。

因此,通常做法是将替代项括在括号中,以最大程度地减少关于它们开始和结束位置的混淆。

替代项从左到右尝试,因此找到的第一个使整个表达式匹配的替代项将被选择。

这意味着替代项不一定是贪婪的。

例如:当用foo|foot匹配barefoot时,只有foo部分会匹配,因为这是第一个尝试的替代项,并且它成功匹配了目标字符串。(当我们使用括号捕获匹配文本时,这可能并不重要。)

还要记住,|在方括号内被解释为字面意思,因此如果您写[fee|fie|foe],实际上只匹配[feio|]

示例:

替代项示例
表达式结果
foo(bar|foo)
匹配字符串foobarfoofoo

5.6. 元字符 - 子表达式

括号结构( ... )也可用于定义正则表达式子表达式。

搜索后,您可以调用任何子表达式,还可以将子表达式用作掩码。

子表达式根据其左括号从左到右的顺序进行编号。

第一个子表达式编号为1,最多支持90个子表达式(整个正则表达式匹配编号为0 – 您可以将其替换为$0$&)。

以下是一些示例:

子表达式
表达式结果
(foobar){8,10}
匹配包含8、9或10个foobar实例的字符串
foob([0-9]|a+)r
匹配foob0rfoob1rfoobarfoobaarfoobaar

关于"替换为"模板的注意事项:

示例:

让我们将日期21.01.2018倒置为2018.01.21
  搜索:(\d{2})\.(\d{2})\.(\d{4})
  替换为:$3.$2.$1

5.7. 元字符 - 反向引用

元字符\1\9被解释为反向引用。\n匹配先前匹配的子表达式n

以下是一些示例:

反向引用示例
表达式结果
(.)\1+
匹配aaaacc
(.+)\1+
也匹配abab123123
(['"]?)(\d+)\1
匹配"13"(双引号中)、'4'(单引号中)或77(无引号)等

6. 断言(前瞻和后瞻断言)

正向前瞻断言:foo(?=bar)仅在bar之前匹配foo,并且bar不包含在匹配中。

负向前瞻断言:foo(?!bar)仅在后面不跟bar时匹配foo

正向后瞻断言:(?<=foo)bar仅在foo之后匹配bar,并且foo不包含在匹配中。

负向后瞻断言:(?<!foo)bar仅在前面没有foo前缀时匹配bar

限制:

7. 非捕获组

语法:(?:expr)

这种组没有"索引",对反向引用不可见。当我们想要对子表达式进行分组,但不想将其保存为字符串的匹配/捕获部分时,使用非捕获组。使用非捕获组可以加快正则表达式的工作速度。

非捕获组
表达式结果
(https?|ftp)://([^/\r\n]+)
https://doublecmd.sourceforge.io中匹配httpsdoublecmd.sourceforge.io
(?:https?|ftp)://([^/\r\n]+)
https://doublecmd.sourceforge.io中仅匹配doublecmd.sourceforge.io

8. 原子组

语法:(?>expr|expr|...)

原子组是非捕获组的特殊情况:如果模式的一部分已经找到,这种分组会禁用括号组的回溯。原子组工作更快,对于优化具有许多不同表达式的组很有用。

例如,a(bc|b)c匹配abccabca(?>bc|b)c匹配abcc但不匹配abc,因为引擎被禁止回溯并尝试将组设置为b

9. Unicode类别

Unicode标准为字符类别命名。这些是2字母字符串。例如Lu是大写字母,Ll是小写字母。而1字母的大类别L是所有字母。

Unicode类别
类别描述
L
字母
Lu
大写字母
Ll
小写字母
Lt
标题大小写字母
Lm
修饰符字母
Lo
其他字母
M
标记
Mn
非间距标记
Mc
间距组合标记
Me
封闭标记
N
数字
Nd
十进制数字
Nl
字母数字
No
其他数字
P
标点符号
Pc
连接符标点
Pd
连字符标点
Ps
开标点
Pe
闭标点
Pi
初始标点
Pf
末尾标点
Po
其他标点
S
符号
Sm
数学符号
Sc
货币符号
Sk
修饰符符号
So
其他符号
Z
分隔符
Zs
空格分隔符
Zl
行分隔符
Zp
段落分隔符
C
其他
Cc
控制
Cf
格式
Cs
代理
Co
私有使用
Cn
未分配

元字符\p表示指定类别的一个Unicode字符。语法:\pL\p{L}用于1字母名称,\p{Lu}用于2字母名称。

元字符\P是反向的,它表示不在指定类别中的一个Unicode字符。

这些元字符在字符类中也受支持。

10. 修饰符

单个修饰符的语法:(?i)表示打开,(?-i)表示关闭。允许多个修饰符,如:(?msgxr-imsgxr)

修饰符用于更改正则表达式的行为。修饰符仅影响(?imsgxr-imsgxr)运算符之后的正则表达式部分。

这些修饰符中的任何一个都可以嵌入到正则表达式本身中。如果修饰符内联到子表达式中,则它仅影响该子表达式。

i
执行不区分大小写的模式匹配(使用系统中安装的区域设置)。默认关闭。
m
将字符串视为多行。即,将^$从仅匹配字符串的开头或结尾更改为匹配字符串内任何行的开头或结尾,另请参见行分隔符。默认关闭。
s
将字符串视为单行。即,将.更改为匹配任何字符,甚至是行分隔符(另请参见行分隔符),而它通常不会匹配。默认打开。
g
非标准修饰符。关闭它将把所有后续运算符切换到非贪婪模式(默认情况下此修饰符打开)。因此,如果修饰符g关闭,则+的工作方式为+?*的工作方式为*?等。
x
通过允许空格和注释来扩展模式的可读性(见下文说明)。默认关闭。
r
非标准修饰符。如果设置,则范围а-я额外包括俄语字母ёА-Я额外包括Ёа-Я包括所有俄语字母。默认打开。
#
(?#text):注释,text被忽略。请注意,TRegExpr在看到)时关闭注释,因此无法在注释中放入字面)

以下是一些示例:

Perl扩展示例
表达式结果
(?i)Saint-Petersburg
匹配Saint-petersburgSaint-Petersburg
(?i)Saint-(?-i)Petersburg
匹配Saint-Petersburg但不匹配Saint-petersburg
(?i)(Saint-)?Petersburg
匹配Saint-petersburgsaint-petersburg
((?i)Saint-)?Petersburg
匹配saint-Petersburg但不匹配saint-petersburg

修饰符x本身需要更多的解释。

它告诉忽略既不带反斜杠也不在字符类中的空格。

您可以使用它将正则表达式分解为(稍微)更可读的部分。

#字符也被视为引入注释的元字符,例如:

(
  (abc) # 注释1
    |   # 您可以使用空格来格式化正则表达式 - TRegExpr会忽略它
  (efg) # 注释2
)

这也意味着如果您想在模式中使用真正的空格或#字符(在字符类之外,它们不受x影响),您必须转义它们或使用八进制或十六进制转义进行编码。

总的来说,这些功能大大提高了正则表达式文本的可读性。


有效的HTML 4.0过渡 CSS有效!