O Double Commander usa a biblioteca gratuita TRegExpr escrita por Andrey Sorokin.
A maioria das explicações vem do arquivo de ajuda desta biblioteca.
Expressões regulares são um método amplamente utilizado para especificar padrões de busca em textos. Caracteres especiais (metacaracteres) nos permitem especificar, por exemplo, que uma string específica que estamos procurando aparece no início ou no fim de uma linha, ou contém n ocorrências de um caractere ou grupo de caracteres.
O Double Commander suporta expressões regulares nas seguintes funcionalidades:
A biblioteca TRegExpr suporta dois modos de operação: ANSI e Unicode. Ao pesquisar em arquivos de texto, o Double Commander usa ambos (dependendo da codificação do arquivo). Ao pesquisar por nome, o Unicode é usado.
Qualquer caractere individual corresponde a si mesmo, a menos que seja um metacaractere com significado especial descrito abaixo.
Uma série de caracteres corresponde a essa mesma série na string de destino, portanto, o padrão bluh corresponderá a bluh na string de destino.
Podemos fazer com que metacaracteres ou sequências de escape sejam interpretados literalmente prefixando-os com uma barra invertida \, por exemplo: o metacaractere ^ corresponde ao início da string, mas \^ corresponde ao caractere ^, \\ corresponde a \ e assim por diante.
Aqui estão alguns exemplos:
| Exemplos de Correspondência Simples | |
|---|---|
| Expressão | Resultado |
foobar |
Corresponde à string foobar |
\^FooBarPtr |
Corresponde a ^FooBarPtr |
Caracteres podem ser especificados usando uma sintaxe de sequência de escape semelhante à usada em C e Perl: \n corresponde a uma nova linha, \t a uma tabulação, etc.
Mais genericamente, \xnn, onde nn é uma sequência de dígitos hexadecimais, corresponde ao caractere com valor ASCII nn.
Se precisar de códigos de caracteres Unicode (wide), você pode usar \x{nnnn}, onde nnnn é um ou mais dígitos hexadecimais.
| Sequências de Escape | |
|---|---|
| Expressão | Resultado |
\xnn |
Caractere com código ASCII nn |
\x{nnnn} |
Caractere com código ASCII nnnn (um byte para texto comum, dois bytes para Unicode) |
\t |
Tabulação (HT/TAB), o mesmo que \x09 |
\n |
Nova linha (NL/LF), o mesmo que \x0a |
\r |
Retorno de carro (CR), o mesmo que \x0d |
\f |
Alimentação de formulário (FF), o mesmo que \x0c |
\a |
Alerta (bipe) (BEL), o mesmo que \x07 |
\e |
Escape (ESC), o mesmo que \x1b |
Aqui estão alguns exemplos:
| Exemplos de Sequência de Escape | |
|---|---|
| Expressão | Resultado |
foo\x20bar |
Corresponde a foo bar (observe o espaço no meio) |
\tfoobar |
Corresponde a foobar precedido por uma tabulação |
Você pode especificar uma classe de caracteres colocando uma lista de caracteres entre [], o que corresponderá a qualquer um caractere da lista.
Se o primeiro caractere após o [ for ^, a classe corresponderá a qualquer caractere não contido na lista.
Dentro da lista, o caractere - é usado para especificar um intervalo, portanto a-z representa todos os caracteres de a até z, inclusive.
Se você quiser que o próprio - seja um membro da classe, coloque-o no início ou no fim da lista, ou escape-o com uma barra invertida.
Se desejar usar ], pode colocá-lo no início da lista ou escapá-lo com uma barra invertida.
| Classes de Caracteres | |
|---|---|
| Expressão | Resultado |
[-az] |
Corresponde a a, z e - |
[az-] |
Corresponde a a, z e - |
[a\-z] |
Corresponde a a, z e - |
[a-z] |
Corresponde a todas as 26 letras minúsculas de a a z |
[\n-\x0D] |
Corresponde a qualquer um de \x10, \x11, \x12, \x13 |
[\d-t] |
Corresponde a qualquer dígito, - ou t |
[]-a] |
Corresponde a qualquer caractere de ] a a |
Aqui estão alguns exemplos:
| Exemplos de Classe de Caracteres | |
|---|---|
| Expressão | Resultado |
foob[aeiou]r |
Localiza strings como foobar, foober, etc., mas não foobbr, foobcr, etc. |
foob[^aeiou]r |
Localiza strings como foobbr, foobcr, etc., mas não foobar, foober, etc. |
Metacaracteres são a essência das expressões regulares, são caracteres especiais.
Existem diferentes tipos de metacaracteres, conforme descrito abaixo.
Algumas expressões ajudam a detectar a separação de linhas.
| Separadores de Linha | |
|---|---|
| Expressão | Resultado |
^ |
Início da linha |
$ |
Fim da linha |
\A |
Início do texto |
\Z |
Fim do texto |
. |
Qualquer caractere na linha |
Aqui estão alguns exemplos:
| Exemplos de Separador de Linha | |
|---|---|
| Expressão | Resultado |
^foobar |
Corresponde apenas se a string foobar estiver no início da linha |
foobar$ |
Corresponde apenas se a string foobar estiver no fim da linha |
^foobar$ |
Corresponde apenas se a string foobar for a única na linha |
foob.r |
Corresponde a strings como foobar, foobbr, foob1r, etc. |
Por padrão, o metacaractere ^ garante correspondência apenas no início da string/texto de entrada e o metacaractere $ apenas no final. Separadores de linha embutidos não serão correspondidos por ^ ou $.
No entanto, você pode querer tratar a string como um buffer de várias linhas, de modo que ^ corresponda após qualquer separador de linha dentro da string e $ corresponda antes de qualquer separador de linha. Você pode fazer isso ativando o modificador m.
\A e \Z funcionam como ^ e $, mas não fazem correspondências múltiplas quando o modificador m é usado, enquanto ^ e $ corresponderão em cada separador de linha interno.
Por padrão, . corresponde a qualquer caractere, mas se você desativar o modificador s, o . não corresponderá a separadores de linha embutidos.
O TRegExpr lida com separadores de linha de acordo com o Padrão Técnico Unicode (Technical Standard #18):
^ está no início da string de entrada e, se o modificador m estiver ativado, também após qualquer ocorrência de \x0D\x0A ou \x0A ou \x0D (suporte Unicode: \x2028 ou \x2029 ou \x0B ou \x0C ou \x85). Observe que não há linha vazia dentro da sequência \x0D\x0A.
$ está no fim da string de entrada e, se o modificador m estiver ativado, também antes de qualquer ocorrência de \x0D\x0A ou \x0A ou \x0D (suporte Unicode: \x2028 ou \x2029 ou \x0B ou \x0C ou \x85). Observe que não há linha vazia dentro da sequência \x0D\x0A.
. corresponde a qualquer caractere, mas se o modificador s estiver desativado, o . não corresponde a \x0D\x0A e \x0A e \x0D (suporte Unicode: \x2028 e \x2029 e \x0B e \x0C e \x85).
Observe que ^.*$ (padrão de linha vazia) não corresponderá a uma string vazia dentro da sequência \x0D\x0A, mas corresponderá a uma string vazia dentro da sequência \x0A\x0D.
Algumas expressões ajudam a detectar grupos de caracteres.
| Classes Predefinidas | |
|---|---|
| Expressão | Resultado |
\w |
Caracteres alfanuméricos (incluindo _), ou seja, [0-9A-Za-z_] |
\W |
Caracteres não alfanuméricos |
\d |
Caracteres numéricos |
\D |
Caracteres não numéricos |
\s |
Qualquer caractere de espaço em branco (o mesmo que [ \t\n\r\f]) |
\S |
Caracteres que não são de espaço em branco |
Você pode usar \w, \d e \s dentro de suas classes de caracteres personalizadas.
Aqui estão alguns exemplos:
| Exemplos de Classe Predefinida | |
|---|---|
| Expressão | Resultado |
foob\dr |
Corresponde a strings como foob1r, foob6r, etc., mas não foobar, foobbr, etc. |
foob[\w\s]r |
Corresponde a strings como foobar, foob r, foobbr, etc., mas não foob=r, etc. |
Um limite de palavra (\b) é a posição entre dois caracteres que possui um \w em um lado e um \W no outro (em qualquer ordem), contando os caracteres imaginários no início e no fim da string como correspondentes a \W.
| Limites de Palavras | |
|---|---|
| Expressão | Resultado |
\b |
Corresponde ao limite da palavra |
\B |
Corresponde a algo que não é limite de palavra |
Qualquer item de uma expressão regular pode ser seguido por outro tipo de metacaractere – um iterador.
Usando esses metacaracteres, você pode especificar o número de ocorrências do caractere, metacaractere ou subexpressão anterior.
| Iteradores | |
|---|---|
| Expressão | Resultado |
* |
Zero ou mais vezes ("ganancioso"), semelhante a {0,} |
+ |
Uma ou mais vezes ("ganancioso"), semelhante a {1,} |
? |
Zero ou uma vez ("ganancioso"), semelhante a {0,1} |
{n} |
Exatamente n vezes ("ganancioso") |
{n,} |
Pelo menos n vezes ("ganancioso") |
{n,m} |
Pelo menos n vezes, mas no máximo m vezes ("ganancioso") |
*? |
Zero ou mais vezes ("não ganancioso"), semelhante a {0,}? |
+? |
Uma ou mais vezes ("não ganancioso"), semelhante a {1,}? |
?? |
Zero ou uma vez ("não ganancioso"), semelhante a {0,1}? |
{n}? |
Exatamente n vezes ("não ganancioso") |
{n,}? |
Pelo menos n vezes ("não ganancioso") |
{n,m}? |
Pelo menos n vezes, mas no máximo m vezes ("não ganancioso") |
Portanto, números entre chaves na forma {n,m} especificam o número mínimo n e o número máximo m de vezes que o item deve corresponder.
A forma {n} é equivalente a {n,n} e corresponde exatamente n vezes.
A forma {n,} corresponde n ou mais vezes.
Não há limite para o tamanho de n ou m, mas números grandes atrasarão a execução e consumirão mais memória.
Se as chaves aparecerem em qualquer outro contexto, serão tratadas como caracteres comuns.
Aqui estão alguns exemplos:
| Exemplos de Iterador | |
|---|---|
| Expressão | Resultado |
foob.*r |
Corresponde a strings como foobar, foobalkjdflkj9r e foobr |
foob.+r |
Corresponde a strings como foobar, foobalkjdflkj9r, etc., mas não foobr |
foob.?r |
Corresponde a strings como foobar, foobbr e foobr, mas não foobalkj9r |
fooba{2}r |
Corresponde à string foobaar |
fooba{2,}r |
Corresponde a strings como foobaar, foobaaar, foobaaaar, etc. |
fooba{2,3}r |
Corresponde a strings como foobaar ou foobaaar, mas não foobaaaar |
Uma pequena explicação sobre "ganância" (greediness).
O modo "ganancioso" pega o máximo possível, o "não ganancioso" pega o mínimo possível.
Por exemplo, b+ e b* aplicados à string abbbbc retornam bbbb, b+? retorna b, b*? retorna uma string vazia, b{2,3}? retorna bb e b{2,3} retorna bbb.
Você pode alternar todos os iteradores para o modo "não ganancioso" (veja o modificador g).
Você pode especificar uma série de alternativas para um padrão usando | para separá-las, portanto, fee|fie|foe corresponderá a fee, fie ou foe na string de destino (o mesmo vale para f(e|i|o)e).
A primeira alternativa inclui tudo desde o último delimitador de padrão ((, [ ou início do padrão) até o primeiro |, e a última alternativa contém tudo desde o último | até o próximo delimitador de padrão.
Por isso, é comum colocar as alternativas entre parênteses, para minimizar confusão sobre onde começam e onde terminam.
As alternativas são tentadas da esquerda para a direita, portanto, a primeira alternativa encontrada que permita a correspondência de toda a expressão será a escolhida.
Isso significa que as alternativas não são necessariamente gananciosas.
Por exemplo: ao comparar foo|foot com barefoot, apenas a parte foo será correspondida, pois foi a primeira alternativa tentada e obteve sucesso na correspondência com a string de destino (isso pode não importar se não estivermos usando parênteses para capturar o texto correspondente).
Lembre-se também de que o | é interpretado literalmente dentro de colchetes, portanto, se você escrever [fee|fie|foe], estará correspondendo apenas a [feio|].
Exemplo:
| Exemplo de Alternativa | |
|---|---|
| Expressão | Resultado |
foo(bar|foo) |
Corresponde às strings foobar ou foofoo |
A construção em parênteses ( ... ) também pode ser usada para definir subexpressões de expressões regulares.
Após a pesquisa, você pode invocar qualquer subexpressão e também usar subexpressões como máscara.
Subexpressões são numeradas da esquerda para a direita na ordem de seus parênteses de abertura.
A primeira subexpressão é numerada como 1, e até 90 subexpressões são suportadas (a correspondência de toda a expressão regular é numerada como 0 – você pode substituí-la por $0 ou $&).
Aqui estão alguns exemplos:
| Subexpressões | |
|---|---|
| Expressão | Resultado |
(foobar){8,10} |
Corresponde a uma string que contenha de 8 a 10 instâncias de foobar |
foob([0-9]|a+)r |
Corresponde a foob0r, foob1r, foobar, foobaar, foobaaar, etc. |
Observação sobre modelos de "Substituir por":
$ ou \ original no modelo, use o prefixo \.1\$ is $2\\rub\\ retornará 1$ is <subexpr2>\rub\.$n, deve colocar n entre chaves {}.a$12bc retornará a<subexpr12>bc, mas a${1}2bc retornará a<subexpr1>2bc.Exemplo:
Vamos inverter uma data de 21.01.2018 para 2018.01.21:
Pesquisa: (\d{2})\.(\d{2})\.(\d{4})
Substituir por: $3.$2.$1
Metacaracteres de \1 a \9 são interpretados como referências retroativas. \n corresponde à subexpressão n correspondida anteriormente.
Aqui estão alguns exemplos:
| Exemplos de Referência Retroativa | |
|---|---|
| Expressão | Resultado |
(.)\1+ |
Corresponde a aaaa e cc |
(.+)\1+ |
Também corresponde a abab e 123123 |
(['"]?)(\d+)\1 |
Corresponde a "13" (entre aspas duplas), '4' (entre aspas simples) ou 77 (sem aspas), etc. |
Lookahead positivo: foo(?=bar) corresponde a foo apenas se estiver antes de bar, e bar não é incluído na correspondência.
Lookahead negativo: foo(?!bar) corresponde a foo apenas se não for seguido por bar.
Lookbehind positivo: (?<=foo)bar corresponde a bar apenas se estiver após foo, e foo não é incluído na correspondência.
Lookbehind negativo: (?<!foo)bar corresponde a bar apenas se não for precedido por foo.
Limitações:
Parênteses para Lookahead devem estar no final da expressão e para Lookbehind devem estar no início da expressão. Portanto, asserções entre alternativas | ou dentro de grupos não são suportadas.
Para o Lookbehind (?<!foo)bar, a expressão regular foo deve ter comprimento fixo, ou seja, consistir apenas de operações de correspondência de comprimento fixo. Quantificadores não são permitidos, exceto chaves com números repetidos {n} ou {n,n}. Classes de caracteres são permitidas aqui, pontos são permitidos, \b e \B são permitidos. Grupos e alternativas não são permitidos.
Para os outros 3 tipos de asserções, as expressões entre parênteses podem ter qualquer complexidade.
Sintaxe: (?:expr).
Tais grupos não têm "índice" e são invisíveis para referências retroativas. Grupos sem captura são usados quando queremos agrupar uma subexpressão, mas não queremos salvá-la como uma parte correspondida/capturada da string. Usar grupos sem captura acelera o trabalho com expressões regulares.
| Grupos Sem Captura | |
|---|---|
| Expressão | Resultado |
(https?|ftp)://([^/\r\n]+) |
Em https://doublecmd.sourceforge.io corresponde a https e doublecmd.sourceforge.io |
(?:https?|ftp)://([^/\r\n]+) |
Em https://doublecmd.sourceforge.io corresponde apenas a doublecmd.sourceforge.io |
Sintaxe: (?>expr|expr|...).
Grupos atômicos são um caso especial de grupos sem captura: esse agrupamento desabilita o backtracking (retrocesso) para o grupo entre parênteses se uma parte do padrão já tiver sido encontrada. Grupos atômicos trabalham mais rápido e são úteis para otimizar grupos com muitas expressões diferentes.
Por exemplo, a(bc|b)c corresponde a abcc e abc, enquanto a(?>bc|b)c corresponde a abcc mas não a abc, porque o motor é proibido de retroceder e tentar definir o grupo como b.
O padrão Unicode dá nomes às categorias de caracteres. São strings de 2 letras. Por exemplo, Lu é uma letra maiúscula, Ll é uma minúscula. E a categoria maior de 1 letra L são todas as letras.
| Categorias Unicode | |
|---|---|
| Categoria | Descrição |
L | Letras |
Lu | Letras maiúsculas |
Ll | Letras minúsculas |
Lt | Letras em caixa de título (Title case) |
Lm | Letras modificadoras |
Lo | Outras letras |
M | Marcas |
Mn | Marcas sem espaçamento |
Mc | Marcas de combinação com espaçamento |
Me | Marcas envolventes |
N | Números |
Nd | Dígitos decimais |
Nl | Letras numéricas |
No | Outros números |
P | Pontuação |
Pc | Pontuação conectora |
Pd | Pontuação de traço (dash) |
Ps | Pontuação de abertura |
Pe | Pontuação de fechamento |
Pi | Pontuação inicial |
Pf | Pontuação final |
Po | Outras pontuações |
S | Símbolos |
Sm | Símbolos matemáticos |
Sc | Símbolos monetários |
Sk | Símbolos modificadores |
So | Outros símbolos |
Z | Separadores |
Zs | Separador de espaço |
Zl | Separador de linha |
Zp | Separador de parágrafo |
C | Outros |
Cc | Controle |
Cf | Formato |
Cs | Substituto (Surrogate) |
Co | Uso privado |
Cn | Não atribuído |
O metacaractere \p denota um caractere Unicode da categoria especificada. Sintaxe: \pL e \p{L} para nomes de 1 letra, \p{Lu} para nomes de 2 letras.
O metacaractere \P é o inverso, denota um caractere Unicode que não está na categoria especificada.
Esses metacaracteres também são suportados dentro de classes de caracteres.
Sintaxe para um único modificador: (?i) para ativar, (?-i) para desativar. Múltiplos modificadores são permitidos, como: (?msgxr-imsgxr).
Modificadores são usados para alterar o comportamento das expressões regulares. Um modificador afeta apenas a parte da expressão regular que segue o operador (?imsgxr-imsgxr).
Qualquer um desses modificadores pode ser embutido na própria expressão regular. Se o modificador estiver embutido em uma subexpressão, ele afetará apenas essa subexpressão.
^ e $ de corresponder apenas ao início ou fim da string para corresponder ao início ou fim de qualquer linha dentro da string, veja também Separadores de linha. Padrão desativado.. para corresponder a qualquer caractere, mesmo separadores de linha (veja também Separadores de linha), o que normalmente não corresponderia. Padrão ativado.g estiver desativado, então + trabalhará como +?, * como *? e assim por diante.а-я inclui adicionalmente a letra russa ё, А-Я inclui Ё, а-Я inclui todas as letras russas. Padrão ativado.texto é ignorado. Observe que o TRegExpr fecha o comentário assim que vê um ), portanto, não há como colocar um ) literal no comentário.Aqui estão alguns exemplos:
| Exemplos de Extensão Perl | |
|---|---|
| Expressão | Resultado |
(?i)Saint-Petersburg |
Corresponde a Saint-petersburg e Saint-Petersburg |
(?i)Saint-(?-i)Petersburg |
Corresponde a Saint-Petersburg mas não a Saint-petersburg |
(?i)(Saint-)?Petersburg |
Corresponde a Saint-petersburg e saint-petersburg |
((?i)Saint-)?Petersburg |
Corresponde a saint-Petersburg mas não a saint-petersburg |
O modificador x em si requer um pouco mais de explicação.
Ele diz para ignorar espaços em branco que não estejam prefixados por barra invertida nem dentro de uma classe de caracteres.
Você pode usá-lo para quebrar sua expressão regular em partes (um pouco) mais legíveis.
O caractere # também é tratado como um metacaractere que introduz comentários, por exemplo:
(
(abc) # comentário 1
| # você pode usar espaços para formatar a regex - o TRegExpr os ignora
(efg) # comentário 2
)
Isso também significa que, se você desejar usar um espaço real ou o caractere # no padrão (fora de uma classe de caracteres, onde eles não são afetados por x), você deve escapá-los ou codificá-los usando sequências de escape octais ou hexadecimais.
No geral, essas funcionalidades melhoram muito a legibilidade de textos de expressões regulares.