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