9.7. Correspondência com padrão

O PostgreSQL disponibiliza três abordagens distintas para correspondência com padrão: o operador LIKE tradicional do SQL; o operador mais recente SIMILAR TO (adicionado ao SQL:1999); e as expressões regulares no estilo POSIX. Além disso, também está disponível a função de correspondência com padrão substring, que utiliza expressões regulares tanto no estilo SIMILAR TO quanto no estilo POSIX.

Dica: Havendo necessidade de correspondência com padrão acima destas, deve ser considerado o desenvolvimento de uma função definida pelo usuário em Perl ou Tcl.

9.7.1. LIKE

cadeia_de_caracteres LIKE padrão [ESCAPE caractere_de_escape]
cadeia_de_caracteres NOT LIKE padrão [ESCAPE caractere_de_escape]

Cada padrão define um conjunto de cadeias de caracteres. A expressão LIKE retorna verdade se a cadeia_de_caracteres estiver contida no conjunto de cadeias de caracteres representado pelo padrão; como esperado, a expressão NOT LIKE retorna falso quando LIKE retorna verdade, e vice-versa, e a expressão equivalente é NOT (cadeia_de_caracteres LIKE padrão).

Quando o padrão não contém os caracteres percentagem ou sublinhado, o padrão representa apenas a própria cadeia de caracteres; neste caso LIKE atua como o operador igual. No padrão o caractere sublinhado (_) representa (corresponde a) qualquer um único caractere; o caractere percentagem (%) corresponde a qualquer cadeia com zero ou mais caracteres.

Alguns exemplos:

'abc' LIKE 'abc'    verdade
'abc' LIKE 'a%'     verdade
'abc' LIKE '_b_'    verdade
'abc' LIKE 'c'      falso

A correspondência com padrão LIKE sempre abrange toda a cadeia de caracteres. Para haver correspondência com o padrão em qualquer posição da cadeia de caracteres, o padrão deve começar e terminar pelo caractere percentagem.

Para corresponder ao próprio caractere sublinhado ou percentagem, sem corresponder a outros caracteres, estes caracteres devem ser precedidos pelo caractere de escape no padrão. O caractere de escape padrão é a contrabarra, mas pode ser definido um outro caractere através da cláusula ESCAPE. Para corresponder ao próprio caractere de escape, devem ser escritos dois caracteres de escape.

Deve ser observado que a contrabarra também possui significado especial nos literais cadeias de caracteres e, portanto, para escrever em uma constante um padrão contendo uma contrabarra devem ser escritas duas contrabarras no comando SQL. Assim sendo, para escrever um padrão que corresponda ao literal contrabarra é necessário escrever quatro contrabarras no comando, o que pode ser evitado escolhendo um caractere de escape diferente na cláusula ESCAPE; assim a contrabarra deixa de ser um caractere especial para o LIKE (Mas continua sendo especial para o analisador de literais cadeias de caracteres e, por isso, continuam sendo necessárias duas contrabarras).

Também é possível fazer com que nenhum caractere sirva de escape declarando ESCAPE ''. Esta declaração tem como efeito desativar o mecanismo de escape, tornando impossível anular o significado especial dos caracteres sublinhado e percentagem no padrão.

Alguns exemplos: (N. do T.)

-- Neste exemplo a contrabarra única é consumida pelo analisador de literais
-- cadeias de caracteres, e não anula o significado especial do _

=> SELECT tablename FROM pg_tables WHERE tablename LIKE '%g\_o%' ESCAPE '\\';

  tablename
--------------
 pg_group
 pg_operator
 pg_opclass
 pg_largeobject

-- Neste exemplo somente uma das duas contrabarras é consumida pelo analisador
-- de literais cadeias de caracteres e, portanto, a segunda contrabarra anula
-- o significado especial do _

=> SELECT tablename FROM pg_tables WHERE tablename LIKE '%g\\_o%' ESCAPE '\\';

 tablename
-----------
 pg_operator
 pg_opclass

-- No Oracle não são necessárias duas contrabarras, como mostrado abaixo:

SQL> SELECT view_name FROM all_views WHERE view_name LIKE 'ALL\_%' ESCAPE '\';

Pode ser utilizada a palavra chave ILIKE no lugar de LIKE para fazer a correspondência não diferenciar letras maiúsculas de minúsculas, conforme o idioma ativo. [1] Isto não faz parte do padrão SQL, sendo uma extensão do PostgreSQL.

O operador ~~ equivale ao LIKE, enquanto ~~* corresponde ao ILIKE. Também existem os operadores !~~ e !~~*, representando o NOT LIKE e o NOT ILIKE respectivamente. Todos estes operadores são específicos do PostgreSQL.

9.7.2. Expressões regulares do SIMILAR TO

cadeia_de_caracteres SIMILAR TO padrão [ESCAPE caractere_de_escape]
cadeia_de_caracteres NOT SIMILAR TO padrão [ESCAPE caractere_de_escape]

O operador SIMILAR TO retorna verdade ou falso conforme o padrão corresponda ou não à cadeia de caracteres fornecida. Este operador é muito semelhante ao LIKE, exceto por interpretar o padrão utilizando a definição de expressão regular do padrão SQL. As expressões regulares do padrão SQL são um cruzamento curioso entre a notação do LIKE e a notação habitual das expressões regulares.

Da mesma forma que o LIKE, o operador SIMILAR TO somente é bem-sucedido quando o padrão corresponde a toda cadeia de caracteres; é diferente do praticado habitualmente nas expressões regulares, onde o padrão pode corresponder a qualquer parte da cadeia de caracteres. Também como o LIKE, o operador SIMILAR TO utiliza _ e % como caracteres curinga, representando qualquer um único caractere e qualquer cadeia de caracteres, respectivamente (são comparáveis ao . e ao .* das expressões regulares POSIX).

Além destas funcionalidades pegas emprestada do LIKE, o SIMILAR TO suporta os seguintes metacaracteres para correspondência com padrão pegos emprestado das expressões regulares POSIX:

Deve ser observado que as repetições limitadas (? e {...}) não estão disponíveis, embora existam no POSIX. Além disso, o ponto (.) não é um metacaractere.

Da mesma forma que no LIKE, a contrabarra desativa o significado especial de qualquer um dos metacaracteres; ou pode ser especificado um caractere de escape diferente por meio da cláusula ESCAPE.

Alguns exemplos:

'abc' SIMILAR TO 'abc'      verdade
'abc' SIMILAR TO 'a'        falso
'abc' SIMILAR TO '%(b|d)%'  verdade
'abc' SIMILAR TO '(b|c)%'   falso

A função substring com três parâmetros, substring(cadeia_de_caracteres FROM padrão FOR caractere_de_escape), permite extrair a parte da cadeia de caracteres que corresponde ao padrão da expressão regular SQL:1999. Assim como em SIMILAR TO, o padrão especificado deve corresponder a toda a cadeia de caracteres, senão a função falha e retorna nulo. Para indicar a parte do padrão que deve ser retornada em caso de sucesso, o padrão deve conter duas ocorrências do caractere de escape seguidas por aspas ("). É retornado o texto correspondente à parte do padrão entre estas marcas.

Alguns exemplos:

substring('foobar' FROM '%#"o_b#"%' FOR '#')   oob
substring('foobar' FROM '#"o_b#"%' FOR '#')    NULL

9.7.3. Expressões regulares POSIX

A Tabela 9-13 mostra os operadores disponíveis para correspondência com padrão utilizando as expressões regulares POSIX.

Tabela 9-13. Operadores de correspondência para expressões regulares

Operador Descrição Exemplo
~ Corresponde à expressão regular, diferenciando maiúsculas e minúsculas 'thomas' ~ '.*thomas.*'
~* Corresponde à expressão regular, não diferenciando maiúsculas e minúsculas 'thomas' ~* '.*Thomas.*'
!~ Não corresponde à expressão regular, diferenciando maiúsculas e minúsculas 'thomas' !~ '.*Thomas.*'
!~* Não corresponde à expressão regular, não diferenciando maiúsculas e minúsculas 'thomas' !~* '.*vadim.*'

As expressões regulares POSIX fornecem uma forma mais poderosa para correspondência com padrão que os operadores LIKE e SIMILAR TO. Muitas ferramentas do Unix, como egrep, sed e awk, utilizam uma linguagem para correspondência com padrão semelhante à descrita aqui.

Uma expressão regular é uma seqüência de caracteres contendo uma definição abreviada de um conjunto de cadeias de caracteres (um conjunto regular). Uma cadeia de caracteres é dita correspondendo a uma expressão regular se for membro do conjunto regular descrito pela expressão regular. Assim como no LIKE, os caracteres do padrão correspondem exatamente aos caracteres da cadeia de caracteres, a não ser quando forem caracteres especiais da linguagem da expressão regular — porém, as expressões regulares utilizam caracteres especiais diferentes dos utilizados pelo LIKE. Diferentemente dos padrões do LIKE, uma expressão regular pode corresponder a qualquer parte da cadeia de caracteres, a não ser que a expressão regular seja explicitamente ancorada ao início ou ao final da cadeia de caracteres.

Alguns exemplos:

'abc' ~ 'abc'    verdade
'abc' ~ '^a'     verdade
'abc' ~ '(b|d)'  verdade
'abc' ~ '^(b|c)' falso

A função substring com dois parâmetros, substring(cadeia_de_caracteres FROM padrão), permite extrair a parte da cadeia de caracteres que corresponde ao padrão da expressão regular POSIX. A função retorna nulo quando não há correspondência, senão retorna a parte do texto que corresponde ao padrão. Entretanto, quando o padrão contém parênteses, é retornada a parte do texto correspondendo à primeira subexpressão entre parênteses (aquela cujo abre parênteses vem primeiro). Podem ser colocados parênteses envolvendo toda a expressão, se for desejado utilizar parênteses em seu interior sem disparar esta exceção. Se for necessária a presença de parênteses no padrão antes da subexpressão a ser extraída, veja os parênteses não-capturantes descritos abaixo.

Alguns exemplos:

substring('foobar' from 'o.b')     oob
substring('foobar' from 'o(.)b')   o

As expressões regulares do PostgreSQL são implementadas utilizando um pacote escrito por Henry Spencer. Grande parte da descrição das expressões regulares abaixo foi copiada textualmente desta parte de seu manual.

9.7.3.1. Detalhes das expressões regulares

As expressões regulares (ERs), conforme definidas no POSIX 1003.2, estão presentes em duas formas: ERs estendidas ou EREs (aproximadamente as do egrep), e ERs básicas ou ERBs (aproximadamente as do ed). O PostgreSQL suporta as duas formas, e também implementa algumas extensões que não fazem parte do padrão POSIX, mas que são muito utilizadas por estarem disponíveis em linguagens de programação como Perl e Tcl. As ERs que utilizam as extensões não-POSIX são chamadas de ERs avançadas ou ERAs nesta documentação. As ERAs são quase um superconjunto exato das EREs, mas as ERBs possuem várias notações incompatíveis (bem como são muito mais limitadas). Primeiro são descritas as formas ERA e ERE, indicando as funcionalidades que se aplicam somente as ERAs, e depois descrevendo como as ERBs diferem.

Nota: A forma das expressões regulares aceitas pelo PostgreSQL pode ser escolhida definindo o parâmetro em tempo de execução regex_flavor. A definição usual é advanced, mas pode ser escolhido extended para o máximo de compatibilidade com as versões do PostgreSQL anteriores a 7.4.

Uma expressão regular é definida como uma ou mais ramificações separadas por |. Corresponde a tudo que corresponda a uma de suas ramificações.

Uma ramificação é formada por zero ou mais átomos quantificados, ou restrições, concatenados. Corresponde à correspondência para a primeira, seguida pela correspondência para a segunda, etc.; uma ramificação vazia corresponde à cadeia de caracteres vazia.

Um átomo quantificado é um átomo possivelmente seguido por um único quantificador. Sem o quantificador, corresponde à correspondência para o átomo. Com o quantificador, pode corresponder a um número de ocorrências do átomo. Um átomo pode ser uma das possibilidades mostradas na Tabela 9-14. Os quantificadores possíveis e seus significados estão mostrados na Tabela 9-15.

Uma restrição corresponde a uma cadeia de caracteres vazia, mas corresponde apenas quando determinadas condições são satisfeitas. Uma restrição pode ser utilizada onde um átomo pode ser utilizado, exceto que não pode ser seguida por um quantificador. As restrições simples estão mostradas na Tabela 9-16; algumas outras restrições são descritas posteriormente.

Tabela 9-14. Átomos de expressões regulares

Átomo Descrição
(er) (onde er é qualquer expressão regular) corresponde à correspondência para er, com a correspondência marcada para um possível relato
(?:er) o mesmo acima, mas a correspondência não está marcada para relato (um conjunto de parênteses "não-capturante") (somente ERAs)
. corresponde a qualquer um único caractere
[caracteres] uma expressão de colchetes, correspondendo a qualquer um dos caracteres (consulte a Seção 9.7.3.2 para obter mais detalhes)
\k (onde k é um caractere não alfanumérico) corresponde a este caractere tomado como um caractere ordinário, por exemplo, \\ corresponde ao caractere contrabarra
\c onde c é alfanumérico (possivelmente seguido por outros caracteres) é um escape, consulte a Seção 9.7.3.3 (ERAs somente; nas EREs e nas ERBs corresponde ao c)
{ quando seguido por um caractere que não seja um dígito, corresponde ao caractere abre chaves {; quando seguido por um dígito, é o início de um limite (veja abaixo)
x onde x é um único caractere sem nenhum outro significado, corresponde a este caractere

Uma expressão regular não pode terminar por \.

Nota: Lembre-se que a contrabarra (\) tem um significado especial nos literais cadeias de caracteres do PostgreSQL. Para escrever em uma constante um padrão contendo uma contrabarra, devem ser escritas duas contrabarras na declaração.

Tabela 9-15. Quantificadores de expressão regular

Quantificador Corresponde
* uma seqüência de 0 ou mais correspondências do átomo
+ uma seqüência de 1 ou mais correspondências do átomo
? uma seqüência de 0 ou 1 correspondência do átomo
{m} uma seqüência de exatamente m correspondências do átomo
{m,} uma seqüência de m ou mais correspondências do átomo
{m,n} uma seqüência de m a n (inclusive) correspondências do átomo; m não pode ser maior do que n
*? versão não-voraz do *
+? versão não-voraz do +
?? versão não-voraz do ?
{m}? versão não-voraz do {m}
{m,}? versão não-voraz do {m,}
{m,n}? versão não-voraz do {m,n}

As formas que utilizam {...} são conhecidas como limites. Os números m e n dentro dos limites são inteiros decimais sem sinal, com valores permitidos entre 0 e 255, inclusive.

Quantificadores não-vorazes (disponíveis apenas nas ERAs) correspondem às mesmas possibilidades que seus semelhantes normais (vorazes), mas preferem o menor número em vez do maior número de correspondências. Consulte a Seção 9.7.3.5 para obter mais detalhes.

Nota: Um quantificador não pode vir imediatamente após outro quantificador. Um quantificador não pode começar uma expressão ou uma subexpressão, ou seguir ^ ou |.

Tabela 9-16. Restrições de expressão regular

Restrição Descrição
^ corresponde no início da cadeia de caracteres
$ corresponde no fim da cadeia de caracteres
(?=er) olhar à frente positiva [a] — corresponde em qualquer ponto a partir de onde começa a parte da cadeia de caracteres que corresponde à er (somente ERAs)
(?!er) olhar à frente negativa [b] — corresponde em qualquer ponto a partir de onde começa uma parte da cadeia de caracteres que não corresponde à er (somente ERAs)
Notas:
a. (?=padrão) — olhar à frente positiva (positive lookahead) corresponde à cadeia de caracteres de procura em qualquer ponto onde começa uma cadeia de caracteres correspondendo ao padrão. Esta é uma correspondência não capturante, ou seja, a correspondência não é capturada para um possível uso posterior. Por exemplo 'Windows (?=95|98|NT|2000)' corresponde a "Windows" em "Windows 2000", mas não a "Windows" em "Windows 3.1". Olhar à frente não consome caracteres, ou seja, após ocorrer a correspondência a procura pela próxima ocorrência começa imediatamente após a última ocorrência, e não após os caracteres compreendidos pelo olhar à frente. Introduction to Regular Expressions (N. do T.)
b. (?!padrão) — olhar à frente negativa (negative lookahead) corresponde à cadeia de caracteres de procura em qualquer ponto onde começa uma cadeia de caracteres que não corresponde ao padrão. Esta é uma correspondência não capturante, ou seja, a correspondência não é capturada para um possível uso posterior. Por exemplo 'Windows (?!95|98|NT|2000)' corresponde a "Windows" em "Windows 3.1", mas não a "Windows" em "Windows 2000". Olhar à frente não consome caracteres, ou seja, após ocorrer a correspondência a procura pela próxima ocorrência começa imediatamente após a última ocorrência, e não após os caracteres compreendidos pelo olhar à frente. Introduction to Regular Expressions (N. do T.)

Alguns exemplos: (N. do T.)

substring('Windows 2000' FROM 'Windows (?=95|98|NT|2000)')     Windows
substring('Windows 3.1'  FROM 'Windows (?=95|98|NT|2000)')     NULL
substring('Windows 2000' FROM 'Windows (?!95|98|NT|2000)')     NULL
substring('Windows 3.1'  FROM 'Windows (?!95|98|NT|2000)')     Windows

As restrições de olhar à frente não podem conter referências para trás (consulte a Seção 9.7.3.3), e todos os parênteses dentro das mesmas são considerados não-capturantes.

9.7.3.2. Expressões de colchetes

Uma expressão de colchetes é uma lista de caracteres entre []. Normalmente corresponde a qualquer um único caractere da lista (mas veja abaixo). Se a lista começar por ^, corresponde a qualquer um único caractere não presente no restante da lista (mas veja abaixo). Se dois caracteres da lista estiverem separados por -, isto representa a forma abreviada de todos os caracteres entre estes dois (inclusive) na seqüência de intercalação (collating sequence [2] [3] [4] [5] ) como, por exemplo, [0-9] em ASCII corresponde a qualquer dígito decimal. É ilegal dois intervalos compartilharem uma mesma extremidade como, por exemplo, a-c-e. Os intervalos são dependentes da seqüência de classificação dos caracteres, e os programas portáveis devem evitar esta dependência.

Para incluir o literal ] na lista, deve ser feito com que seja o primeiro caractere (seguindo um possível ^). Para incluir o literal -, deve ser feito com que seja o primeiro ou o último caractere, ou a segunda extremidade de um intervalo. Para utilizar o literal - como a primeira extremidade do intervalo, deve-se colocá-lo entre [. e .] para torná-lo um elemento de classificação (veja abaixo). Com exceção destes caracteres, algumas combinações utilizando [ (veja os próximos parágrafos), e escapes (somente ERAs), todos os outros caracteres especiais perdem seu significado especial dentro da expressão de colchetes. Em particular, \ não é especial ao seguir as regras das EREs ou ERBs, embora seja especial (como introdução de escape) nas ERAs.

Dentro da expressão de colchetes, o elemento de classificação (um caractere, uma seqüência de vários caracteres que é classificada como sendo um único caractere, ou o nome de uma seqüência de classificação) entre [. e .] representa a seqüência de caracteres deste elemento de classificação. A seqüência é um único elemento da lista da expressão de colchetes. Uma expressão de colchetes contendo um elemento de classificação com vários caracteres pode, portanto, corresponder a mais de um caractere. Por exemplo, se a seqüência de classificação incluir o elemento de classificação ch, então a expressão regular [[.ch.]]*c corresponde aos cinco primeiros caracteres de chchcc.

Nota: Atualmente o PostgreSQL não possui elementos de classificação de vários caracteres. Esta informação descreve um possível comportamento futuro.

Dentro da expressão de colchetes, um elemento de classificação entre [= e =] é uma classe de equivalência, representando as seqüências de caracteres de todos os elementos de classificação equivalentes a este elemento, incluindo o próprio (Se não existirem outros elementos de classificação equivalentes, o tratamento é como se os delimitadores envoltórios fossem [. e .]). Por exemplo, se o e ^ são membros de uma classe de equivalência, então [[=o=]], [[=^=]] e [o^] são todos sinônimos. Uma classe de equivalência não pode ser a extremidade de um intervalo.

Dentro da expressão de colchetes, o nome de uma classe de caracteres entre [: e :] representa a lista de todos os caracteres pertencentes a esta classe. Os nomes das classes de caracteres padrão são: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit. Estes nomes representam as classes de caracteres definidas em ctype. O idioma pode fornecer outras. Uma classe de caracteres não pode ser usada como extremidade de um intervalo.

Existem dois casos especiais de expressões de colchetes: as expressões de colchetes [[:<:]] e [[:>:]] são restrições, correspondendo a cadeias de caracteres vazias no início e no fim da palavra, respectivamente. Uma palavra é definida como a seqüência de caracteres de palavra, que não é nem precedida nem seguida por caractere de palavra. Um caractere de palavra é um caractere alnum (conforme definido em ctype) ou um sublinhado. Isto é uma extensão, compatível mas não especificada pelo POSIX 1003.2, devendo ser utilizada com cautela em programas onde se deseja a portabilidade para outros sistemas. Os escapes de restrição descritos abaixo geralmente são preferíveis (não são mais padrão que estes, mas com certeza são mais fáceis de serem digitados).

9.7.3.3. Escapes de expressão regular

Escapes são seqüências especiais começando por \ seguida por um caractere alfanumérico. Os escapes se apresentam em diversas variedades: entrada de caractere, abreviaturas de classe, escapes de restrição e referências para trás. Uma \ seguida por um caractere alfanumérico que não constitua um escape válido é ilegal nas ERAs. Nas EREs não existem escapes: fora da expressão de colchetes, uma \ seguida por um caractere alfanumérico representa tão somente este caractere como um caractere comum, e dentro da expressão de colchetes, a \ é um caractere comum; Esta última é uma verdadeira incompatibilidade entre EREs e ERAs.

Os escapes de entrada de caractere existem para tornar mais fácil a especificação de caracteres não-imprimíveis, ou de alguma outra maneira inconvenientes, nas expressões regulares. Estão mostrados na Tabela 9-17.

Os escapes de abreviatura de classe fornecem abreviaturas para certas classes de caracteres comumente utilizadas. Estão mostrados na Tabela 9-18.

O escape de restrição é uma restrição, correspondendo à cadeia de caracteres vazia caso ocorram determinadas condições, escrita como um escape. Estão mostrados na Tabela 9-19.

Uma referência para trás (\n) corresponde à mesma cadeia de caracteres correspondida pela subexpressão entre parênteses anterior especificada pelo número n (consulte a Tabela 9-20). Por exemplo, ([bc])\1 corresponde a bb ou cc, mas não a bc ou cb. A subexpressão deve preceder inteiramente à referência para trás na expressão regular. As subexpressões são numeradas na ordem de seu parêntese de abertura. Parênteses não-capturantes não definem subexpressões.

Nota: Deve-se ter em mente que a \ de abertura do escape deve ser dobrada ao se entrar o padrão usando uma constante cadeia de caracteres do SQL. Por exemplo:

'123' ~ '^\\d{3}' verdade

Tabela 9-17. Escapes entrada de caractere em expressão regular

Escape Descrição
\a caractere de alerta (bell), como na linguagem C
\b voltar apagando (backspace), como na linguagem C
\B sinônimo de \ para ajudar a reduzir a necessidade de contrabarras dobradas
\cX (onde X é qualquer caractere) o caractere cujos 5 bits de mais baixa ordem são os mesmos de X, e cujos outros bits são todos zero
\e o caractere cujo nome da seqüência de classificação é ESC ou, na falta deste, o caractere com valor octal 033
\f avanço de formulário, como na linguagem C
\n nova-linha, como na linguagem C
\r retorno-de-carro, como na linguagem C
\t tabulação horizontal, como na linguagem C
\uwxyz (onde wxyz são exatamente quatro dígitos hexadecimais) o caractere Unicode U+wxyz na ordem de bytes local
\Ustuvwxyz (onde stuvwxyz são exatamente oito dígitos hexadecimais) reservado para uma extensão hipotética do Unicode para 32 bits
\v tabulação vertical, como na linguagem C
\xhhh (onde hhh é qualquer seqüência de dígitos hexadecimais) o caractere cujo valor hexadecimal é 0xhhh (um único caractere não importando quantos dígitos hexadecimais são utilizados)
\0 o caractere cujo valor é 0
\xy (onde xy são exatamente dois dígitos octais, e não uma referência para trás) o caractere cujo valor octal é 0xy
\xyz (onde xyz são exatamente três dígitos octais, e não uma referência para trás) o caractere cujo valor octal é 0xyz

Os dígitos hexadecimais são 0-9, a-f e A-F. Os dígitos octais são 0-7.

Os escapes de entrada de caractere são sempre tomados como caracteres comuns. Por exemplo, \135 é ] em ASCII, mas \135 não termina uma expressão de colchetes.

Tabela 9-18. Escapes de abreviatura de classe em expressão regular

Escape Descrição
\d [[:digit:]]
\s [[:space:]]
\w [[:alnum:]_] (deve ser observado que inclui o sublinhado)
\D [^[:digit:]]
\S [^[:space:]]
\W [^[:alnum:]_] (deve ser observado que inclui o sublinhado)

Dentro das expressões de colchetes, \d, \s e \w perdem seus colchetes externos, e \D, \S e \W são ilegais (Portanto, por exemplo, [a-c\d] equivale a [a-c[:digit:]]. Também, [a-c\D], que equivale a [a-c^[:digit:]], é ilegal).

Tabela 9-19. Escapes de restrição em expressão regular

Escape Descrição
\A corresponde apenas no início da cadeia de caracteres (veja na Seção 9.7.3.5 como isto difere de ^)
\m corresponde apenas no início da palavra
\M corresponde apenas no final da palavra
\y corresponde apenas no início ou no final da palavra
\Y corresponde apenas no ponto que não é nem o início nem o final da palavra
\Z corresponde apenas no final da cadeia de caracteres (veja na Seção 9.7.3.5 como isto difere de $)

Uma palavra é definida como na especificação de [[:<:]] e [[:>:]] acima. Os escapes de restrição são ilegais dentro de expressões de colchetes.

Tabela 9-20. Referências para trás em expressões regulares

Escape Descrição
\m (onde m é um dígito diferente de zero) uma referência para trás à m'ésima subexpressão
\mnn (onde m é um dígito diferente de zero, e nn são mais alguns dígitos, e o valor decimal mnn não é maior do que o número de parênteses capturantes fechados até este ponto) uma referência para trás à mnn'ésima subexpressão

Nota: Existe uma ambigüidade histórica inerente entre as entradas de caractere em octal para escapes e referências para trás, que é solucionado por heurística, como mostrado acima. Um zero na frente sempre indica um escape octal. Um único dígito diferente de zero, não seguido por outro dígito, é sempre assumido como uma referência para trás. Uma seqüência de vários dígitos não começada por zero é assumida como uma referência para trás se vier após uma subexpressão adequada (ou seja, o número está na faixa legal de referências para trás), senão é assumida como um octal.

9.7.3.4. Metassintaxe em expressão regular

Além da sintaxe principal descrita acima, existem algumas formas especiais e uma miscelânea de facilidades de sintaxe disponíveis.

Normalmente, a variedade da expressão regular sendo utilizada é determinada por regex_flavor, mas pode ser mudada pelo prefixo diretriz. Se a expressão regular começar por ***:, o restante da expressão regular é assumido como sendo uma ARE a despeito de regex_flavor. Se a expressão regular começar por ***=, o restante da expressão regular é assumido como sendo um literal cadeia de caracteres, com todos os caracteres considerados como sendo caracteres comuns.

Uma ERA pode começar por opções incorporadas: uma seqüência (?xyz) (onde xyz é um ou mais caracteres alfabéticos) especifica opções que afetam o restante da expressão regular. Estas opções substituem qualquer opção previamente determinada (incluindo a variedade da expressão regular e a diferenciação de maiúsculas e minúsculas). As letras das opções disponíveis estão mostradas na Tabela 9-21.

Tabela 9-21. Letras de opção incorporada em ERA

Opção Descrição
b o restante da expressão regular é uma ERB
c correspondência fazendo distinção entre letras maiúsculas e minúsculas (substitui o tipo do operador)
e o restante da expressão regular é uma ERE
i correspondência não fazendo distinção entre letras maiúsculas e minúsculas (consulte a Seção 9.7.3.5) (substitui o tipo do operador)
m sinônimo histórico para n
n correspondência sensível à nova-linha (consulte a Seção 9.7.3.5)
p correspondência sensível à nova-linha parcial (consulte a Seção 9.7.3.5)
q o restante da expressão regular é um literal cadeia de caracteres ("entre aspas"), todos caracteres são comuns
s correspondência não sensível à nova-linha (padrão)
t sintaxe amarrada (padrão; veja abaixo)
w correspondência sensível a nova-linha parcial inversa ("estranha") (consulte a Seção 9.7.3.5)
x sintaxe expandida (veja abaixo)

As opções incorporadas passam a valer no fecha parênteses ")" que termina a seqüência. Podem aparecer apenas no início de uma ERA (após a diretriz ***:, caso exista).

Além da sintaxe de expressão regular usual (amarrada), na qual todos os caracteres possuem significado, existe uma sintaxe expandida, disponível especificando-se a opção incorporada x. Na sintaxe expandida, os caracteres de espaço-em-branco na expressão regular são ignorados, assim como todos os caracteres entre a # e a próxima nova-linha (ou o fim da expressão regular). Isto permite colocar parágrafos e comentários em uma expressão regular complexa. Existem três exceções para esta regra básica:

  • um caractere de espaço em branco ou # precedido por \ é retido

  • espaço em branco ou # dentro da expressão de colchetes é retido

  • espaço em branco e comentários são ilegais dentro de símbolos multicaractere, como o (?:

Para esta finalidade os caracteres de espaço-em-branco são espaço, tabulação, nova-linha e qualquer outro caractere que pertença a classe de caracteres space.

Por fim, em uma ERA, fora das expressões de colchetes, a seqüência (?#ttt) (onde ttt é qualquer texto não contendo um )) é um comentário, completamente ignorado. Novamente, isto não é permitido entre os caracteres dos símbolos multicaractere, como o (?:. Estes comentários são mais um artefato histórico do que uma funcionalidade útil, e sua utilização está obsoleta; deve ser usada a sintaxe expandida em seu lugar.

Nenhuma destas extensões da metassintaxe está disponível quando uma diretriz inicial ***= especificar que a entrada do usuário deve ser tratada como um literal cadeia de caracteres em vez de uma expressão regular.

9.7.3.5. Regras de correspondência de expressão regular

Quando uma expressão regular corresponde a mais de uma parte de uma dada cadeia de caracteres, a expressão regular corresponde à parte que começa primeiro. Se a expressão regular puder corresponder a mais de uma parte da cadeia de caracteres começando neste ponto, então corresponderá à correspondência mais longa possível, ou corresponderá à correspondência mais curta possível, dependendo se a expressão regular é voraz (greedy) ou não-voraz (non-greedy).

Se a expressão regular é voraz ou não, é determinado pelas seguintes regras:

  • A maioria dos átomos, e todas as restrições, não possuem atributos de voracidade (porque não podem corresponder a quantidades variáveis de texto de qualquer forma).

  • A adição de parênteses em torno da expressão regular não muda sua voracidade.

  • Um átomo quantificado por um quantificador de repetição fixo ({m} ou {m}?) possui a mesma voracidade (possivelmente nenhuma) do próprio átomo.

  • Um átomo quantificado por outros quantificadores normais (incluindo {m,n} com m igual a n) é voraz (prefere a correspondência mais longa).

  • Um átomo quantificado por um quantificador não voraz (incluindo {m,n}? com m igual a n) é não-voraz (prefere a correspondência mais curta).

  • Uma ramificação — ou seja, uma expressão regular que não possua o operador de nível mais alto | — possui a mesma voracidade do primeiro átomo quantificado nesta que possui o atributo de voracidade.

  • Uma expressão regular formada por duas ou mais ramificações conectadas pelo operador | é sempre voraz.

As regras acima associam os atributos de voracidade não apenas aos átomos quantificados individualmente, mas também com as ramificações e as expressões regulares inteiras contendo átomos quantificados. Isto significa que a correspondência é feita de uma forma que a ramificação, ou toda a expressão regular, corresponda à parte da cadeia de caracteres mais longa ou mais curta possível como um todo. Uma vez que seja determinado o comprimento de toda a correspondência, a parte desta que corresponde a uma determinada subexpressão é determinada com base no atributo de voracidade desta subexpressão, com as subexpressões que começam primeiro na expressão regular tendo prioridade sobre as que começam depois.

Exemplo do que isto significa:

SELECT substring('XY1234Z', 'Y*([0-9]{1,3})');
Resultado: 123
SELECT substring('XY1234Z', 'Y*?([0-9]{1,3})');
Resultado: 1

No primeiro caso, a expressão regular como um todo é voraz porque Y* é voraz. Pode corresponder a partir do Y, e corresponde à cadeia de caracteres mais longa possível começando neste ponto, ou seja, Y123. A saída é a parte entre parênteses da expressão, ou seja, 123. No segundo caso, a expressão regular como um todo não é voraz porque Y*? é não voraz. Pode corresponder a partir do Y, e corresponde à cadeia de caracteres mais curta possível começando neste ponto, ou seja, Y1. A subexpressão [0-9]{1,3} é voraz, mas não pode mudar a decisão para o comprimento de correspondência geral; portanto é forçada a corresponder apenas ao 1.

Em resumo, quando a expressão regular contém tanto subexpressões vorazes quanto não vorazes, o comprimento total da correspondência é o mais longo possível ou o mais curto possível, de acordo com o atributo atribuído a expressão regular como um todo. Os atributos atribuídos às subexpressões afetam somente quanto desta correspondência estas podem "comer" com relação a cada uma outra.

Os quantificadores {1,1} e {1,1}? podem ser utilizados para obrigar voracidade e não-voracidade, respectivamente, nas subexpressões ou na expressão regular como um todo.

Os comprimentos de correspondência são medidos em caracteres, e não em elementos de classificação. Uma cadeia de caracteres vazia é considerada mais longa do que nenhuma correspondência. Por exemplo: bb* corresponde aos três caracteres do meio de abbbc; (week|wee)(night|knights) coresponde a todos os dez caracteres de weeknights; quando é feita a correspondência entre (.*).* e abc, a subexpressão entre parênteses corresponde a todos os três caracteres; e quando é feita a correspondência entre (a*)* e bc, tanto toda a expressão regular quanto a subexpressão entre parênteses correspondem a uma cadeia de caracteres vazia.

Se for especificada uma correspondência não diferenciando maiúsculas de minúsculas, o efeito é como se toda a distinção entre letras maiúsculas e minúsculas tivesse desaparecido do alfabeto. Quando um caractere alfabético que existe em minúscula e maiúscula aparece como um caractere comum fora da expressão de colchetes, este é efetivamente transformado em uma expressão de colchetes contendo as duas representações: por exemplo, x se torna [xX]. Quando aparece dentro de uma expressão de colchetes, todas as outras representações são adicionadas à expressão de colchetes: por exemplo, [x] se torna [xX] e [^x] se torna [^xX].

Se for especificada uma correspondência sensível a nova-linha, o . e as expressões de colchetes utilizando ^ nunca vão corresponder ao caractere de nova-linha (portanto a correspondência nunca atravessa as novas-linhas, a menos que a expressão regular determine explicitamente que isto seja feito), e ^ e $ vão corresponder à cadeia de caracteres vazia após e antes da nova-linha, respectivamente, além de corresponderem ao início e fim da cadeia de caracteres, respectivamente. Mas os escapes \A e \Z das ERAs continuam a corresponder apenas ao início e fim da cadeia de caracteres.

Se for especificada a correspondência sensível a nova-linha parcial, isto afeta o . e as expressões de colchetes como na correspondência sensível a nova-linha, mas não o ^ e o $.

Se for especificada a correspondência sensível a nova-linha parcial inversa, isto afeta o ^ e o $ como na correspondência sensível a nova-linha, mas não o . e as expressões de colchetes. Não é muito útil mas é fornecido para simetria.

9.7.3.6. Limites e compatibilidade

Nenhum limite específico é imposto para o comprimento das expressões regulares nesta implementação. Entretanto, os programas que pretendem ser altamente portáveis não devem utilizar expressões regulares mais longas do que 256 bytes, porque uma implementação em conformidade com o POSIX pode não aceitar estas expressões regulares.

A única funcionalidade das ERAs realmente incompatível com as EREs do POSIX, é que a \ não perde seu significado especial dentro das expressões de colchetes. Todas as outras funcionalidades das ERAs utilizam uma sintaxe que é ilegal ou possuem efeitos não definidos ou não especificados nas EREs POSIX; a sintaxe de diretrizes na forma *** está fora da sintaxe POSIX tanto para as ERBs quanto para as EREs.

Muitas extensões das ERAs foram pegas emprestadas do Perl, mas algumas foram modificadas para que ficassem limpas, e umas poucas extensões do Perl não estão presentes. Entre as incompatibilidades a serem notadas estão \b, \B, a falta de um tratamento especial para a nova-linha final, a adição de expressões de colchetes complementadas para as coisas afetadas pela correspondência sensível à nova-linha, as restrições nos parênteses e referências para trás nas restrições de procura adiante, e a semântica de correspondência contendo correspondência mais longa/mais curta (em vez de primeira correspondência).

Existem duas incompatibilidades significativas entre as sintaxes das ERAs e das ERE reconhecida pelas versões do PostgreSQL anteriores a 7.4:

  • Nas ERAs, a \ seguida por um caractere alfanumérico é um escape ou um erro, enquanto nas versões anteriores, era apenas uma outra forma de escrever o caractere alfanumérico. Isto não deve causar problemas, porque não havia razão para escrever esta seqüência nas versões anteriores.

  • Nas ERAs, a \ permanece sendo um caractere especial dentro de [], portanto o literal \ dentro da expressão de colchetes deve ser escrito como \\.

Embora estas diferenças provavelmente não devam criar problemas para a maioria dos aplicativos, podem ser evitadas se for necessário definindo regex_flavor como extended.

9.7.3.7. Expressões regulares básicas

As ERBs diferem das EREs sob vários aspectos. |, + e ? são caracteres comuns e não existe nada equivalente para suas funcionalidades. Os delimitadores para limites são \{ e \}, com { e } por si só sendo caracteres comuns. Os parênteses para as subexpressões aninhadas são \( e \), com ( e ) por si só sendo caracteres comuns. ^ é um caractere comum exceto no início da expressão regular ou no início de uma subexpressão entre parênteses, $ é um caractere comum exceto no final da expressão regular ou no final de uma subexpressão entre parênteses, e * é um caractere comum se aparecer no início da expressão regular ou no início de uma subexpressão entre parênteses, (após um possível ^ de abertura). Por fim, referências para trás de um único dígito estão disponíveis, e \< e \> são sinônimos de [[:<:]] e [[:>:]] respectivamente; nenhum outro escape está disponível.

9.7.4. Exemplos

Nota: Seção escrita pelo tradutor, não fazendo parte do manual original.

Exemplo 9-4. Utilização de expressão regular em consulta

Neste exemplo são utilizadas expressões regulares em consultas a uma tabela. São mostradas, também, consultas semelhantes utilizando a função REGEXP_LIKE do Oracle 10g, para efeitos de comparação. [6]

Deve ser observado que no PostgreSQL quando se usa SIMILAR TO deve haver caractere de escape antes do sublinhado que não é metacaractere ("\\_"), mesmo entre colchetes, enquanto quando se usa o operador "~" deve haver caractere de escape antes do ponto que não é metacaractere ("\\."), ou ser colocado entre colchetes ("[.]") para que este perca o seu significado especial. O PostgreSQL utiliza a função similar_escape() para converter as expressões regulares no estilo SQL:1999 para o estilo POSIX, para poder usá-las em seu processador de expressões regulares.

A função REGEXP_LIKE do Oracle 10g é semelhante ao operador "~" do PostgreSQL, mas enquanto na função REGEXP_LIKE é necessária apenas uma contrabarra para o escape de metacaracteres, no operador "~" são necessárias duas contrabarras, porque a primeira é consumida pelo interpretador de literais cadeia de caracteres. Nos dois casos, como é habitual nas expressões regulares, a correspondência se dá em qualquer ponto, a não ser que sejam utilizados os metacaracteres ^ e $ para ancorar, explicitamente, a correspondência no início ou no fim da cadeia de caracteres, respectivamente.

Abaixo está mostrado o script usado para criar e carregar a tabela:

\!chcp 1252
CREATE TABLE textos(texto VARCHAR(40));
INSERT INTO textos VALUES ('www.apache.org');
INSERT INTO textos VALUES ('pgdocptbr.sourceforge.net');
INSERT INTO textos VALUES ('WWW.PHP.NET');
INSERT INTO textos VALUES ('www-130.ibm.com');
INSERT INTO textos VALUES ('Julia Margaret Cameron');
INSERT INTO textos VALUES ('Sor Juana Inés de la Cruz');
INSERT INTO textos VALUES ('Inês Pedrosa');
INSERT INTO textos VALUES ('Amy Semple McPherson');
INSERT INTO textos VALUES ('Mary McCarthy');
INSERT INTO textos VALUES ('Isabella Andreine');
INSERT INTO textos VALUES ('Jeanne Marie Bouvier de la Motte Guyon');
INSERT INTO textos VALUES ('Maria Tinteretto');
INSERT INTO textos VALUES ('');
INSERT INTO textos VALUES ('  '||chr(9)||chr(10)||chr(11)||chr(12)||chr(13));
INSERT INTO textos VALUES ('192.168.0.15');
INSERT INTO textos VALUES ('pgsql-bugs-owner@postgresql.org');
INSERT INTO textos VALUES('00:08:54:15:E5:FB');

A seguir estão mostradas as consultas efetuadas juntamente com seus resultados:

  1. Selecionar textos contendo um ou mais caracteres de "a" até "z", seguidos por um ponto, seguido por um ou mais caracteres de "a" até "z", seguidos por um ponto, seguido por um ou mais caracteres de "a" até "z".

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '([a-z]+).([a-z]+).([a-z]+)';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '^([a-z]+)\\.([a-z]+)\\.([a-z]+)$';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '^([a-z]+)[.]([a-z]+)[.]([a-z]+)$';
      
                 texto
      ---------------------------
       www.apache.org
       pgdocptbr.sourceforge.net
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '^([a-z]+)\.([a-z]+)\.([a-z]+)$');
      -- ou
      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '^([a-z]+)[.]([a-z]+)[.]([a-z]+)$');
      
      TEXTO
      ----------------------------------------
      www.apache.org
      pgdocptbr.sourceforge.net
      WWW.PHP.NET
      
  2. Selecionar textos contendo um ou mais caracteres alfanuméricos, sublinhado ou hífen, seguidos por um ponto, seguido por um ou mais caracteres alfanuméricos, sublinhado ou hífen, seguidos por um ponto, seguido por um ou mais caracteres alfanuméricos ou sublinhado (\w corresponde a [a-zA-Z0-9_], ou seja, alfanuméricos e sublinhado).

    • PostgreSQL 8.0.0

      => SELECT texto
      -> FROM textos
      -> WHERE texto SIMILAR TO '([[:alnum:]\\_-]+).([[:alnum:]\\_-]+).([[:alnum:]\\_]+)';
      -- ou
      -> WHERE texto SIMILAR TO '([\\w-]+).([\\w-]+).([\\w]+)';
      -- ou
      -> WHERE texto ~ '^([[:alnum:]_-]+)\\.([[:alnum:]_-]+)\\.([[:alnum:]_]+)$';
      -- ou
      -> WHERE texto ~ '^(([[:alnum:]_-]+)\\.){2}([[:alnum:]_]+)$';
      -- ou
      -> WHERE texto ~ '^([\\w-]+)\\.([\\w-]+)\\.([\\w]+)$';
      -- ou
      -> WHERE texto ~ '^(([\\w-]+)\\.){2}([\\w]+)$';
      
                 texto
      ---------------------------
       www.apache.org
       pgdocptbr.sourceforge.net
       WWW.PHP.NET
       www-130.ibm.com
      
    • Oracle 10g

      SQL> SELECT texto
       2  FROM textos
       3  WHERE REGEXP_LIKE(texto, '^([[:alnum:]_-]+)\.([[:alnum:]_-]+)\.([[:alnum:]_]+)$');
      
      TEXTO
      ----------------------------------------
      www.apache.org
      pgdocptbr.sourceforge.net
      WWW.PHP.NET
      www-130.ibm.com
      
  3. Selecionar textos começando pela letra "S" maiúscula (_* equivale a %).

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO 'S%';
      -- ou
      => SELECT texto FROM textos WHERE texto SIMILAR TO 'S_*';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '^S';
      
                 texto
      ---------------------------
       Sor Juana Inés de la Cruz
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '^S');
      
      TEXTO
      ----------------------------------------
      Sor Juana Inés de la Cruz
      
  4. Selecionar textos contendo "Mc" em qualquer posição.

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%Mc%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ 'Mc';
      
              texto
      ----------------------
       Amy Semple McPherson
       Mary McCarthy
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, 'Mc');
      
      TEXTO
      ----------------------------------------
      Amy Semple McPherson
      Mary McCarthy
      
  5. Selecionar textos terminados por "on".

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%on';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ 'on$';
      
                       texto
      ----------------------------------------
       Julia Margaret Cameron
       Amy Semple McPherson
       Jeanne Marie Bouvier de la Motte Guyon
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, 'on$');
      
      TEXTO
      ----------------------------------------
      Julia Margaret Cameron
      Amy Semple McPherson
      Jeanne Marie Bouvier de la Motte Guyon
      
  6. Selecionar textos começando por "J" e terminando por "n".

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO 'J%n';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '^J.*n$';
      
                       texto
      ----------------------------------------
       Julia Margaret Cameron
       Jeanne Marie Bouvier de la Motte Guyon
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '^J.*n$');
      
      TEXTO
      ----------------------------------------
      Julia Margaret Cameron
      Jeanne Marie Bouvier de la Motte Guyon
      
  7. Selecionar textos contendo "Cameron" ou "Marie" em qualquer posição.

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%(Cameron|Marie)%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '(Cameron|Marie)';
      
                       texto
      ----------------------------------------
       Julia Margaret Cameron
       Jeanne Marie Bouvier de la Motte Guyon
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '(Cameron|Marie)');
      
      TEXTO
      ----------------------------------------
      Julia Margaret Cameron
      Jeanne Marie Bouvier de la Motte Guyon
      
  8. Selecionar textos contendo "Maria", "Marie" ou "Mary" (não seleciona "Margaret").

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%Mar(ia|ie|y)%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ 'Mar(ia|ie|y)';
      
                       texto
      ----------------------------------------
       Mary McCarthy
       Jeanne Marie Bouvier de la Motte Guyon
       Maria Tinteretto
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, 'Mar(ia|ie|y)');
      
      TEXTO
      ----------------------------------------
      Mary McCarthy
      Jeanne Marie Bouvier de la Motte Guyon
      Maria Tinteretto
      
  9. Selecionar textos sem nenhum caractere, ou com somente espaços em branco (no Oracle texto sem nenhum caractere é igual a nulo).

    • PostgreSQL 8.0.0

      => SELECT texto, length(texto) FROM textos WHERE texto SIMILAR TO '[[:space:]]*';
      -- ou
      => SELECT texto, length(texto) FROM textos WHERE texto SIMILAR TO '\\s*';
      -- ou
      => SELECT texto, length(texto) FROM textos WHERE texto ~ '^[[:space:]]*$';
      -- ou
      => SELECT texto, length(texto) FROM textos WHERE texto ~ '^\\s*$';
      
       texto | length
      -------+--------
             |      0
             |      7
      
    • Oracle 10g

      SQL> SELECT texto, length(texto) FROM textos WHERE REGEXP_LIKE(texto, '^[[:space:]]*$');
      
      TEXTO                                    LENGTH(TEXTO)
      ---------------------------------------- -------------
                                                           7
      
  10. Selecionar textos contendo a letra "W" minúscula ou maiúscula, seguida por uma ou mais letras "W" minúsculas ou maiúsculas.

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%[Ww]([Ww]+)%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '[Ww]([Ww]+)';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '[Ww]{2,}';
      
            texto
      -----------------
       www.apache.org
       WWW.PHP.NET
       www-130.ibm.com
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '[Ww]([Ww]+)');
      -- ou
      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '[Ww]{2,}');
      
      TEXTO
      ----------------------------------------
      www.apache.org
      WWW.PHP.NET
      www-130.ibm.com
      
  11. Selecionar textos contendo "Inês", com letras maiúsculas ou minúsculas, com ou sem acento, em qualquer posição.

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%[Ii][nN][eéêEÉÊ][Ss]%';
      -- ou
      => SELECT texto FROM textos WHERE lower(to_ascii(texto)) SIMILAR TO '%ines%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '[Ii][nN][eéêEÉÊ][Ss]';
      -- ou
      => SELECT texto FROM textos WHERE lower(to_ascii(texto)) ~ 'ines';
      
                 texto
      ---------------------------
       Sor Juana Inés de la Cruz
       Inês Pedrosa
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '[Ii][nN][eéêEÉÊ][Ss]');
      
      TEXTO
      ----------------------------------------
      Sor Juana Inés de la Cruz
      Inês Pedrosa
      
  12. Selecionar textos contendo dígitos.

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto SIMILAR TO '%[0-9]+%';
      -- ou
      => SELECT texto FROM textos WHERE texto SIMILAR TO '%[[:digit:]]+%';
      -- ou
      => SELECT texto FROM textos WHERE texto SIMILAR TO '%\\d+%';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '[0-9]+';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '[[:digit:]]+';
      -- ou
      => SELECT texto FROM textos WHERE texto ~ '\\d+';
      
             texto
      -------------------
       www-130.ibm.com
       192.168.0.15
       00:08:54:15:E5:FB
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '[0-9]+');
      -- ou
      SQL> SELECT texto FROM textos WHERE REGEXP_LIKE(texto, '[[:digit:]]+');
      
      TEXTO
      -----------------
      www-130.ibm.com
      192.168.0.15
      00:08:54:15:E5:FB
      
  13. Selecionar textos não contendo espaços em branco (texto sem nenhum caractere não possui espaço em branco, mas no Oracle texto sem nenhum caractere é igual a nulo).

    • PostgreSQL 8.0.0

      => SELECT texto FROM textos WHERE texto NOT SIMILAR TO '%\\s%';
      -- ou
      => SELECT texto FROM textos WHERE texto NOT SIMILAR TO '%[[:space:]]%';
      -- ou
      => SELECT texto FROM textos WHERE texto !~ '\\s';
      -- ou
      => SELECT texto FROM textos WHERE texto !~ '[[:space:]]';
      
                    texto
      ---------------------------------
       www.apache.org
       pgdocptbr.sourceforge.net
       WWW.PHP.NET
       www-130.ibm.com
      
       192.168.0.15
       pgsql-bugs-owner@postgresql.org
       00:08:54:15:E5:FB
      
    • Oracle 10g

      SQL> SELECT texto FROM textos WHERE NOT REGEXP_LIKE(texto, '[[:space:]]');
      
      TEXTO
      ----------------------------------------
      www.apache.org
      pgdocptbr.sourceforge.net
      WWW.PHP.NET
      www-130.ibm.com
      192.168.0.15
      pgsql-bugs-owner@postgresql.org
      00:08:54:15:E5:FB
      
  14. Selecionar textos que podem ser endereços de IPv4.

    • PostgreSQL 8.0.0

      => SELECT texto
      -> FROM textos
      -> WHERE texto ~ '^[[:digit:]]{1,3}[.][[:digit:]]{1,3}[.][[:digit:]]{1,3}[.][[:digit:]]{1,3}$';
      -- ou
      -> WHERE texto ~ '^([[:digit:]]{1,3}[.]){3}[[:digit:]]{1,3}$';
      
          texto
      --------------
       192.168.0.15
      
    • Oracle 10g

      SQL> SELECT texto
       2  FROM textos
       3  WHERE REGEXP_LIKE(texto, '^[[:digit:]]{1,3}[.][[:digit:]]{1,3}[.][[:digit:]]{1,3}[.][[:digit:]]{1,3}$');
      -- ou
       3  WHERE REGEXP_LIKE(texto, '^([[:digit:]]{1,3}[.]){3}[[:digit:]]{1,3}$');
      
      TEXTO
      ------------
      192.168.0.15
      
  15. Selecionar textos que podem ser endereços de correio eletrônico.

    • PostgreSQL 8.0.0

      => SELECT texto
      -> FROM textos
      -> WHERE texto SIMILAR TO '[a-zA-Z][\\w.-]*@[a-zA-Z][\\w.-]*.[a-zA-Z]+';
      -- ou
      -> WHERE texto SIMILAR TO '[a-zA-Z][[:alnum:]\\_.-]*@[a-zA-Z][[:alnum:]\\_.-]*.[a-zA-Z]+';
      -- ou
      -> WHERE texto ~ '^[a-zA-Z][\\w.-]*@[a-zA-Z][\\w.-]*[.][a-zA-Z]+$';
      -- ou
      -> WHERE texto ~ '^[a-zA-Z][[:alnum:]_.-]*@[a-zA-Z][[:alnum:]_.-]*[.][a-zA-Z]+$';
      
                    texto
      ---------------------------------
       pgsql-bugs-owner@postgresql.org
      
    • Oracle 10g

      SQL> SELECT texto
       2  FROM textos
       3  WHERE REGEXP_LIKE(texto, '^[[:alnum:]_\.-]+@[[:alnum:]_\.-]+\.[a-zA-Z]+$');
      
      TEXTO
      -------------------------------
      pgsql-bugs-owner@postgresql.org
      
  16. Selecionar textos que podem ser endereços de hardware de placa Ethernet, formados por 48 bits, expressos como 12 dígitos hexadecimais (0-9 e A-F maiúsculas), no formato 12:34:56:78:9A:BC.

    • PostgreSQL 8.0.0

      => SELECT texto
      -> FROM textos
      -> WHERE texto ~ '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$';
      -- ou
      -> WHERE texto ~ '^([0-9A-F]{2}:){5}[0-9A-F]{2}$';
      
             texto
      -------------------
       00:08:54:15:E5:FB
      
    • Oracle 10g

      SQL> SELECT texto
       2  FROM textos
       3  WHERE REGEXP_LIKE(texto, '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$');
      -- ou
       3  WHERE REGEXP_LIKE(texto, '^([0-9A-F]{2}:){5}[0-9A-F]{2}$');
      
      TEXTO
      -----------------
      00:08:54:15:E5:FB
      

Exemplo 9-5. Utilização de expressão regular em restrição de verificação

Neste exemplo são utilizadas expressões regulares em restrição de verificação na criação de uma tabela. São utilizadas expressões regulares para verificar se os dados fornecidos para os campos de endereço de correio eletrônico, CEP de 9 dígitos com hífen, CEP de 8 dígitos sem hífen e unidade da federação são válidos. É mostrada, também, a criação de uma tabela semelhantes utilizando a função REGEXP_LIKE do Oracle 10g na restrição de verificação, para efeitos de comparação. [7]

Deve ser observado que no Oracle 10g só é necessário utilizar uma contrabarra antes do ponto, e não duas como no PostgreSQL 8.0.0.

Abaixo está mostrada a execução do exemplo no PostgreSQL 8.0.0:

=> CREATE TABLE contactos(
(>  email VARCHAR(40)   -- endereço de correio eletrônico
(>      CONSTRAINT chk_email
(>          CHECK (email ~ '^[a-zA-Z][[:alnum:]_.-]*@[a-zA-Z][[:alnum:]_.-]*[.][a-zA-Z]+$'),
(>  cep8 CHAR(8)        -- CEP com oito dígitos sem hífen
(>      CONSTRAINT chk_cep8
(>          CHECK (cep8 ~ '^[[:digit:]]{8}$'),
(>  cep9 CHAR(9)        -- CEP com nove dígitos com hífen
(>      CONSTRAINT chk_cep9
(>          CHECK (cep9 ~ '^[[:digit:]]{5}-[[:digit:]]{3}$'),
(>  uf CHAR(2)          -- unidade da federação
(>      CONSTRAINT chk_uf
(>          CHECK (uf ~ '^A(C|L|M|P)|BA|CE|DF|ES|GO|M(A|G|S|T)|P(A|B|E|I|R)|R(J|N|O|R|S)|S(C|E|P)|TO$')
(> );

=> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160-900','DF');
=> INSERT INTO contactos VALUES('clp.decomcamara.gov.br','70160900','70160-900','DF');
ERRO: a nova linha para a relação "contactos" viola a restrição de verificação "chk_email"
=> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','7016090','70160-900','DF');
ERRO: a nova linha para a relação "contactos" viola a restrição de verificação "chk_cep8"
=> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160900','DF');
ERRO: a nova linha para a relação "contactos" viola a restrição de verificação "chk_cep9"
=> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160-900','DG');
ERRO: a nova linha para a relação "contactos" viola a restrição de verificação "chk_uf"

=> SELECT * FROM contactos;

          email          |   cep8   |   cep9    | uf
-------------------------+----------+-----------+----
 clp.decom@camara.gov.br | 70160900 | 70160-900 | DF

Abaixo está mostrada a execução de exemplo semelhante no Oracle 10g:

SQL> CREATE TABLE contactos(
 2    email VARCHAR(40)   -- endereço de correio eletrônico
 3        CONSTRAINT chk_email
 4            CHECK (REGEXP_LIKE(email, '^[a-zA-Z][[:alnum:]_.-]*@[a-zA-Z][[:alnum:]_.-]*[.][a-zA-Z]+$')),
 5    cep8 CHAR(8)        -- CEP com oito dígitos sem hífen
 6        CONSTRAINT chk_cep8
 7            CHECK (REGEXP_LIKE(cep8, '^[[:digit:]]{8}$')),
 8    cep9 CHAR(9)        -- CEP com nove dígitos com hífen
 9        CONSTRAINT chk_cep9
 10            CHECK (REGEXP_LIKE(cep9, '^[[:digit:]]{5}-[[:digit:]]{3}$')),
 11    uf CHAR(2)          -- unidade da federação
 12        CONSTRAINT chk_uf
 13            CHECK (REGEXP_LIKE(uf, '^A(C|L|M|P)|BA|CE|DF|ES|GO|M(A|G|S|T)|P(A|B|E|I|R)|R(J|N|O|R|S)|S(C|E|P)|TO$'))
 14  );

SQL> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160-900','DF');

SQL> INSERT INTO contactos VALUES('clp.decomcamara.gov.br','70160900','70160-900','DF');
INSERT INTO contactos VALUES('clp.decomcamara.gov.br','70160900','70160-900','DF')
*
ERRO na linha 1:
ORA-02290: restrição de verificação (SCOTT.CHK_EMAIL) violada

SQL> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','7016090','70160-900','DF');
INSERT INTO contactos VALUES('clp.decom@camara.gov.br','7016090','70160-900','DF')
*
ERRO na linha 1:
ORA-02290: restrição de verificação (SCOTT.CHK_CEP8) violada

SQL> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160900','DF');
INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160900','DF')
*
ERRO na linha 1:
ORA-02290: restrição de verificação (SCOTT.CHK_CEP9) violada

SQL> INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160-900','DG');
INSERT INTO contactos VALUES('clp.decom@camara.gov.br','70160900','70160-900','DG')
*
ERRO na linha 1:
ORA-02290: restrição de verificação (SCOTT.CHK_UF) violada

SQL> SELECT * FROM contactos;

EMAIL                                    CEP8     CEP9      UF
---------------------------------------- -------- --------- --
clp.decom@camara.gov.br                  70160900 70160-900 DF

Exemplo 9-6. Utilização de expressão regular em colunas concatenadas

Neste exemplo é utilizada uma expressão regular na consulta a uma tabela, onde o primeiro nome e o sobrenome estão armazenados em colunas diferentes, para localizar o nome de uma pessoa que pode estar armazenado de várias formas diferentes. Abaixo está mostrado o script usado para criar e carregar a tabela:

CREATE TEMPORARY TABLE nomes (nome TEXT, sobrenome TEXT);
INSERT INTO nomes VALUES ('Manuel','da Paróquia');
INSERT INTO nomes VALUES ('SEU MANUEL','DA PAROQUIA');
INSERT INTO nomes VALUES ('Manuel','da Paroquia dos Anjos');
INSERT INTO nomes VALUES ('Manuel da Paróquia',NULL);
INSERT INTO nomes VALUES ('Seu','MANUEL DA PARÓQUIA');
INSERT INTO nomes VALUES ('Dona Maria','da Capela');

Abaixo está mostrada a consulta realizada sobre os campos nome e sobrenome concatenados, para localizar uma pessoa com "Manuel" no nome e "Paróquia" no sobrenome, juntamente com os resultados obtidos.

=> \pset null '(nulo)'
A visualização de nulos é "(nulo)".
=> SELECT *
-> FROM nomes
-> WHERE (COALESCE(nome,'')||COALESCE(sobrenome,'')) ~* 'manuel.*par[oóÓ]quia';
        nome        |       sobrenome
--------------------+-----------------------
 Manuel             | da Paróquia
 SEU MANUEL         | DA PAROQUIA
 Manuel             | da Paroquia dos Anjos
 Manuel da Paróquia | (nulo)
 Seu                | MANUEL DA PARÓQUIA

Exemplo 9-7. Comparação entre o PostgreSQL e o PHP

Neste exemplo é feita a comparação entre a função substring do PostgreSQL e a função preg_match do PHP, utilizando uma expressão regular voraz e outra não voraz, para capturar o texto entre as marcas <a...> e </a> na cadeia de caracteres:

O <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>.

Os resultados são idênticos, mas a função preg_match retorna uma matriz onde o elemento [0] contém o texto que corresponde a todo o padrão, o elemento [1] contém o texto que corresponde à primeira subexpressão entre parênteses capturada, e assim por diante, enquanto a função substring retorna o texto que corresponde à primeira subexpressão entre parênteses apenas. [8]

  • PostgreSQL 8.0.0

    => \set texto '\'O <a href="http://php.net/">PHP</a> possui um excelente '
    => \set texto :texto '<a href="http://php.net/manual">manual</a>.\''
    
    => SELECT substring(:texto,'<a.*>(.*)</a>');
    
     substring
    -----------
     manual
    
    => SELECT substring(:texto,'<a.*?>(.*?)</a>');
    
     substring
    -----------
     PHP
    
  • PHP

    <?php
        $texto = 'O <a href="http://php.net/">PHP</a> possui um excelente '
               . '<a href="http://php.net/manual">manual</a>.';
        preg_match('|<a.*>(.*)</a>|', $texto, $corresp);
        print_r($corresp);
        preg_match('|<a.*?>(.*?)</a>|', $texto, $corresp);
        print_r($corresp);
    ?>
    
    Array
    (
        [0] => <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>
        [1] => manual
    )
    Array
    (
        [0] => <a href="http://php.net/">PHP</a>
        [1] => PHP
    )
    

Exemplo 9-8. Comparação entre o PostgreSQL e o PCRE

Neste exemplo é feita a comparação entre a função substring do PostgreSQL e o programa pcredemo do PCRE - Perl Compatible Regular Expressions, utilizando uma expressão regular voraz e outra não voraz, para capturar o texto entre as marcas <a...> e </a> na cadeia de caracteres:

O <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>.

Os resultados são idênticos, mas o programa pcredemo com a opção -g retorna todas as correspondências encontradas, enquanto a função substring retorna o texto que corresponde à primeira subexpressão entre parênteses apenas. Sem a opção -g, o resultado do pcredemo é idêntico ao do PHP, que utiliza a biblioteca PCRE como suporte às expressões regulares. [9]

  • PostgreSQL 8.0.0

    => \set texto '\'O <a href="http://php.net/">PHP</a> possui um excelente '
    => \set texto :texto '<a href="http://php.net/manual">manual</a>.\''
    
    => SELECT substring(:texto,'<a.*>(.*)</a>');
    
     substring
    -----------
     manual
    
    => SELECT substring(:texto,'<a.*?>(.*?)</a>');
    
     substring
    -----------
     PHP
    
  • PCRE

    $ ./pcredemo -g \
    > '<a.*>(.*)</a>' \
    > 'O <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>.'
    
    Correspondência bem sucedida no deslocamento 2
     0: <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>
     1: manual
    
    $ ./pcredemo -g \
    > '<a.*?>(.*?)</a>' \
    > 'O <a href="http://php.net/">PHP</a> possui um excelente <a href="http://php.net/manual">manual</a>.'
    
    Correspondência bem sucedida no deslocamento 2
     0: <a href="http://php.net/">PHP</a>
     1: PHP
    
    Correspondência bem sucedida novamente no deslocamento 56
     0: <a href="http://php.net/manual">manual</a>
     1: manual
    

Notas

[1]

C, POSIX, pt_BR, etc. (N. do T.)

[2]

collation; collating sequence — Um método para comparar duas cadeias de caracteres comparáveis. Todo conjunto de caracteres possui seu collation padrão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992. (N. do T.)

[3]

SQL Serverintercalação (collation) — é um conjunto de regras que determina como os dados são comparados, ordenados e apresentados. Os dados caractere são classificados de acordo com a informação de intercalação, que inclui o idioma, a ordem de classificação e a diferenciação de letras minúsculas e maiúsculas. SQL Server 2005 Books Online — Glossary of Terms (N. do T.)

[4]

collation é uma classificação apropriada para o idioma. Collation (N. do T.)

[5]

collation — [informática, computadores] — s. intercalação, f. collation | Portuguese | Dictionary & Translation by Babylon (N. do T.)

[6]

Exemplo escrito pelo tradutor, não fazendo parte do manual original. Fora Inês Pedrosa, escritora portuguesa, os demais nomes foram tirados de Women of the Last Millennium.

[7]

Exemplo escrito pelo tradutor, não fazendo parte do manual original. As informações usadas neste exemplo foram retiradas da página Comissão de Legislação Participativa da Câmara dos Deputados. Outros exemplos de expressões regulares podem ser encontrados em Regular Expression Library, Server-Side Validations Using Regular Expressions e Regular Expression HOWTO.

[8]

Exemplo escrito pelo tradutor, baseado no exemplo do livro PHP 5 Programação Poderosa de Andi Gutmans, Stig Saether Bakken e Derik Rethans - Editora Alta Books - 2005 - pág. 187

[9]

Exemplo escrito pelo tradutor, utilizando os parâmetros do exemplo anterior.

SourceForge.net Logo CSS válido!