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
影響),您必須跳脫它們或使用八進位或十六進位跳脫進行編碼。
總的來說,這些功能大大提高了正規表示式文字的可讀性。