Double Commander使用Andrey Sorokin编写的免费库TRegExpr。
大多数解释来自该库的帮助文件。
正则表达式是一种广泛使用的指定文本搜索模式的方法。特殊字符(元字符)允许我们指定,例如,我们正在查找的特定字符串出现在行的开头或结尾,或者包含字符或字符组的n次出现。
Double Commander在以下功能中支持正则表达式:
TRegExp库支持两种操作模式:ANSI和Unicode。在文本文件中搜索时,Double Commander使用两者(取决于文件编码)。在按名称搜索时,使用Unicode。
任何单个字符都匹配自身,除非它是一个具有下面描述的特殊含义的元字符。
一系列字符匹配目标字符串中的该系列字符,因此模式bluh
将匹配目标字符串中的bluh
。
我们可以通过在元字符或转义序列前面加上反斜杠\
来使它们被逐字解释,例如:元字符^
匹配字符串开头,但\^
匹配字符^
,\\
匹配\
等等。
以下是一些示例:
简单匹配示例 | |
---|---|
表达式 | 结果 |
foobar |
匹配字符串foobar |
\^FooBarPtr |
匹配^FooBarPtr |
可以使用类似于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 |
您可以通过将字符列表括在[]
中来指定字符类,这将匹配列表中的任何一个字符。
如果[
后的第一个字符是^
,则该类匹配列表中不包含的任何字符。
在列表中,-
字符用于指定范围,因此a-z
表示从a
到z
的所有字符,包括在内。
如果您希望-
本身成为类的成员,请将其放在列表的开头或结尾,或用反斜杠转义。
如果您希望使用]
,可以将其放在列表的开头或用反斜杠转义。
字符类 | |
---|---|
表达式 | 结果 |
[-az] |
匹配a 、z 和- |
[az-] |
匹配a 、z 和- |
[a\-z] |
匹配a 、z 和- |
[a-z] |
匹配从a 到z 的所有26个小写字母 |
[\n-\x0D] |
匹配任何\x10 、\x11 、\x12 、\x13 |
[\d-t] |
匹配任何数字、- 或t |
[]-a] |
匹配从] 到a 的任何字符 |
以下是一些示例:
字符类示例 | |
---|---|
表达式 | 结果 |
foob[aeiou]r |
查找字符串foobar 、foober 等,但不包括foobbr 、foobcr 等。 |
foob[^aeiou]r |
查找字符串foobbr 、foobcr 等,但不包括foobar 、foober 等。 |
一些表达式有助于检测行分隔。
行分隔符 | |
---|---|
表达式 | 结果 |
^ |
行首 |
$ |
行尾 |
\A |
文本开头 |
\Z |
文本结尾 |
. |
行中任何字符 |
以下是一些示例:
行分隔符示例 | |
---|---|
表达式 | 结果 |
^foobar |
仅当字符串foobar 在行首时匹配 |
foobar$ |
仅当字符串foobar 在行尾时匹配 |
^foobar$ |
仅当字符串foobar 是行中唯一字符串时匹配 |
foob.r |
匹配像foobar 、foobbr 、foob1r 等字符串 |
默认情况下,^
元字符仅保证在输入字符串/文本的开头匹配,$
元字符仅在末尾匹配。嵌入的行分隔符不会被^
或$
匹配。
但是,您可能希望将字符串视为多行缓冲区,这样^
将在字符串内的任何行分隔符后匹配,$
将在任何行分隔符前匹配。您可以通过打开修饰符m来实现。
\A
和\Z
就像^
和$
一样,但当使用修饰符m时,它们不会多次匹配,而^
和$
将在每个内部行分隔符处匹配。
默认情况下,.
元字符匹配任何字符,但如果关闭修饰符s,则.
不会匹配嵌入的行分隔符。
TRegExpr按照Unicode技术标准(技术标准#18)处理行分隔符:
^
在输入字符串的开头,并且如果修饰符m打开,也在\x0D\x0A
或\x0A
或\x0D
的任何出现之后(支持Unicode:\x2028
或\x2029
或\x0B
或\x0C
或\x85
)。请注意,在\x0D\x0A
序列中没有空行。
$
在输入字符串的结尾,并且如果修饰符m打开,也在\x0D\x0A
或\x0A
或\x0D
的任何出现之前(支持Unicode:\x2028
或\x2029
或\x0B
或\x0C
或\x85
)。请注意,在\x0D\x0A
序列中没有空行。
.
匹配任何字符,但如果关闭修饰符s,则.
不匹配\x0D\x0A
和\x0A
和\x0D
(支持Unicode:\x2028
和\x2029
和\x0B
和\x0C
和\x85
)。
请注意,^.*$
(空行模式)不会在\x0D\x0A
序列中匹配空字符串,但会在\x0A\x0D
序列中匹配空字符串。
一些表达式有助于检测字符组。
预定义类 | |
---|---|
表达式 | 结果 |
\w |
字母数字字符(包括_ ),即[0-9A-Za-z_] |
\W |
非字母数字字符 |
\d |
数字字符 |
\D |
非数字字符 |
\s |
任何空格字符(与[ \t\n\r\f] 相同) |
\S |
非空格字符 |
您可以在自定义字符类中使用\w
、\d
和\s
。
以下是一些示例:
预定义类示例 | |
---|---|
表达式 | 结果 |
foob\dr |
匹配像foob1r 、foob6r 等字符串,但不包括foobar 、foobbr 等 |
foob[\w\s]r |
匹配像foobar 、foob r 、foobbr 等字符串,但不包括foob=r 等 |
词边界(\b
)是在其一侧有\w
而另一侧有\W
的两个字符之间的位置(以任一顺序),将字符串开头和结尾的假想字符计为匹配\W
。
词边界 | |
---|---|
表达式 | 结果 |
\b |
匹配词边界 |
\B |
匹配非词边界 |
正则表达式的任何项目都可以跟随另一种类型的元字符 – 迭代器。
使用这些元字符,您可以指定前一个字符、元字符或子表达式的出现次数。
迭代器 | |
---|---|
表达式 | 结果 |
* |
零次或多次("贪婪"),类似于{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
次或更多次。
n
或m
的大小没有限制,但大数字会减慢执行速度并消耗更多内存。
如果花括号出现在任何其他上下文中,它被视为普通字符。
以下是一些示例:
迭代器示例 | |
---|---|
表达式 | 结果 |
foob.*r |
匹配像foobar 、foobalkjdflkj9r 和foobr 等字符串 |
foob.+r |
匹配像foobar 、foobalkjdflkj9r 等字符串,但不包括foobr |
foob.?r |
匹配像foobar 、foobbr 和foobr 等字符串,但不包括foobalkj9r |
fooba{2}r |
匹配字符串foobaar |
fooba{2,}r |
匹配像foobaar 、foobaaar 、foobaaaar 等字符串 |
fooba{2,3}r |
匹配像foobaar 或foobaaar 等字符串,但不包括foobaaaar |
关于"贪婪性"的一点解释。
"贪婪"取尽可能多,"非贪婪"取尽可能少。
例如,b+
和b*
应用于字符串abbbbc
返回bbbb
,b+?
返回b
,b*?
返回空字符串,b{2,3}?
返回bb
,b{2,3}
返回bbb
。
您可以将所有迭代器切换到"非贪婪"模式(参见修饰符g)。
您可以使用|
分隔一系列替代项来为模式指定,因此fee|fie|foe
将匹配目标字符串中的fee
、fie
或foe
(f(e|i|o)e
也是如此)。
第一个替代项包括从上一个模式分隔符((
、[
或模式开头)到第一个|
的所有内容,最后一个替代项包含从最后一个|
到下一个模式分隔符的所有内容。
因此,通常做法是将替代项括在括号中,以最大程度地减少关于它们开始和结束位置的混淆。
替代项从左到右尝试,因此找到的第一个使整个表达式匹配的替代项将被选择。
这意味着替代项不一定是贪婪的。
例如:当用foo|foot
匹配barefoot
时,只有foo
部分会匹配,因为这是第一个尝试的替代项,并且它成功匹配了目标字符串。(当我们使用括号捕获匹配文本时,这可能并不重要。)
还要记住,|
在方括号内被解释为字面意思,因此如果您写[fee|fie|foe]
,实际上只匹配[feio|]
。
示例:
替代项示例 | |
---|---|
表达式 | 结果 |
foo(bar|foo) |
匹配字符串foobar 或foofoo |
括号结构( ... )
也可用于定义正则表达式子表达式。
搜索后,您可以调用任何子表达式,还可以将子表达式用作掩码。
子表达式根据其左括号从左到右的顺序进行编号。
第一个子表达式编号为1,最多支持90个子表达式(整个正则表达式匹配编号为0 – 您可以将其替换为$0
或$&
)。
以下是一些示例:
子表达式 | |
---|---|
表达式 | 结果 |
(foobar){8,10} |
匹配包含8、9或10个foobar 实例的字符串 |
foob([0-9]|a+)r |
匹配foob0r 、foob1r 、foobar 、foobaar 、foobaar 等 |
关于"替换为"模板的注意事项:
$
或\
,请使用前缀\
。1\$ is $2\\rub\\
将返回1$ is <subexpr2>\rub\
。$n
后放置原始数字,则必须用花括号{}
将n
括起来。a$12bc
将返回a<subexpr12>bc
,但a${1}2bc
将返回a<subexpr1>2bc
。示例:
让我们将日期21.01.2018
倒置为2018.01.21
:
搜索:(\d{2})\.(\d{2})\.(\d{4})
替换为:$3.$2.$1
元字符\1
到\9
被解释为反向引用。\n
匹配先前匹配的子表达式n
。
以下是一些示例:
反向引用示例 | |
---|---|
表达式 | 结果 |
(.)\1+ |
匹配aaaa 和cc |
(.+)\1+ |
也匹配abab 和123123 |
(['"]?)(\d+)\1 |
匹配"13" (双引号中)、'4' (单引号中)或77 (无引号)等 |
正向前瞻断言:foo(?=bar)
仅在bar
之前匹配foo
,并且bar
不包含在匹配中。
负向前瞻断言:foo(?!bar)
仅在后面不跟bar
时匹配foo
。
正向后瞻断言:(?<=foo)bar
仅在foo
之后匹配bar
,并且foo
不包含在匹配中。
负向后瞻断言:(?<!foo)bar
仅在前面没有foo
前缀时匹配bar
。
限制:
前瞻的括号必须在表达式的末尾,后瞻的括号必须在表达式的开头。因此不支持在选择|
之间或组内的断言。
对于后瞻(?<!foo)bar
,正则表达式foo
必须是固定长度,即只包含固定长度匹配的操作。不允许使用量词,除了带有重复数字{n}
或{n,n}
的花括号。此处允许使用字符类,允许使用点,允许使用\b
和\B
。不允许使用组和选择。
对于其他3种断言类型,括号中的表达式可以是任意复杂度。
语法:(?:expr)
。
这种组没有"索引",对反向引用不可见。当我们想要对子表达式进行分组,但不想将其保存为字符串的匹配/捕获部分时,使用非捕获组。使用非捕获组可以加快正则表达式的工作速度。
非捕获组 | |
---|---|
表达式 | 结果 |
(https?|ftp)://([^/\r\n]+) |
在https://doublecmd.sourceforge.io 中匹配https 和doublecmd.sourceforge.io |
(?:https?|ftp)://([^/\r\n]+) |
在https://doublecmd.sourceforge.io 中仅匹配doublecmd.sourceforge.io |
语法:(?>expr|expr|...)
。
原子组是非捕获组的特殊情况:如果模式的一部分已经找到,这种分组会禁用括号组的回溯。原子组工作更快,对于优化具有许多不同表达式的组很有用。
例如,a(bc|b)c
匹配abcc
和abc
,a(?>bc|b)c
匹配abcc
但不匹配abc
,因为引擎被禁止回溯并尝试将组设置为b
。
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字符。
这些元字符在字符类中也受支持。
单个修饰符的语法:(?i)
表示打开,(?-i)
表示关闭。允许多个修饰符,如:(?msgxr-imsgxr)
。
修饰符用于更改正则表达式的行为。修饰符仅影响(?imsgxr-imsgxr)
运算符之后的正则表达式部分。
这些修饰符中的任何一个都可以嵌入到正则表达式本身中。如果修饰符内联到子表达式中,则它仅影响该子表达式。
^
和$
从仅匹配字符串的开头或结尾更改为匹配字符串内任何行的开头或结尾,另请参见行分隔符。默认关闭。.
更改为匹配任何字符,甚至是行分隔符(另请参见行分隔符),而它通常不会匹配。默认打开。g
关闭,则+
的工作方式为+?
,*
的工作方式为*?
等。а-я
额外包括俄语字母ё
,А-Я
额外包括Ё
,а-Я
包括所有俄语字母。默认打开。text
被忽略。请注意,TRegExpr在看到)
时关闭注释,因此无法在注释中放入字面)
。以下是一些示例:
Perl扩展示例 | |
---|---|
表达式 | 结果 |
(?i)Saint-Petersburg |
匹配Saint-petersburg 和Saint-Petersburg |
(?i)Saint-(?-i)Petersburg |
匹配Saint-Petersburg 但不匹配Saint-petersburg |
(?i)(Saint-)?Petersburg |
匹配Saint-petersburg 和saint-petersburg |
((?i)Saint-)?Petersburg |
匹配saint-Petersburg 但不匹配saint-petersburg |
修饰符x
本身需要更多的解释。
它告诉忽略既不带反斜杠也不在字符类中的空格。
您可以使用它将正则表达式分解为(稍微)更可读的部分。
#
字符也被视为引入注释的元字符,例如:
( (abc) # 注释1 | # 您可以使用空格来格式化正则表达式 - TRegExpr会忽略它 (efg) # 注释2 )
这也意味着如果您想在模式中使用真正的空格或#
字符(在字符类之外,它们不受x
影响),您必须转义它们或使用八进制或十六进制转义进行编码。
总的来说,这些功能大大提高了正则表达式文本的可读性。