103.7 Expressões regulares
Expressão regular é um conjunto de meta caracteres e caracteres que definem um padrão de texto. Os algoritmos de busca de strings são amplamente usados por várias tarefas de processamento de dados, tanto que os sistemas operacionais do tipo Unix têm sua própria implementação onipresente: Expressões regulares, geralmente abreviadas para REs. As expressões regulares consistem em sequências de caracteres que constituem um padrão genérico usado para localizar e, às vezes, modificar uma sequência correspondente em uma sequência maior de caracteres.
File Globbing
Globbing interpreta os caracteres curinga padrão *
e ?
, listas de caracteres entre colchetes e alguns outros caracteres especiais (como ^
para negar o sentido de uma correspondência). REGEX não é o mesmo que File Globbing.
Caracteres de REGEX
Para usar REGEX, usamos os mesmos caracteres que conhecemos como caracteres curinga, mas aqui eles tem uma função similar ou parecida o que pode entender que fazem a mesma coisa, mas não fazem.
Caracteres | Significado |
---|---|
[] | Significa que existe uma Lista |
^ | Significa Começo de linha |
$ | Significa Fim de linha |
* | Informa que o que vem antes dele é opcional (pode não existir correspondencia) ou pode existir 1 ou mais correspondencias. |
+ | Informa que a correspondencia anterior pode acontecer pelo menos 1 vez (ou muitas vezes). |
? | Significa que o que estiver antes dele não deve se repetir, ou vai aparecer uma única vez. |
. | Significa um caractere qualquer, equivalente ao ? |
\ | É o escape, usamos a contra-barra. |
() | Informa que existe um grupo. |
{1,2} | Número podem ser mudados. Significa que a correspondencia vai aparecer no mínimo 1 vez e no máximo 2. |
| | Significa o operador lógico OU. |
Comandos para usar com REGEX
Para usar regex, temos alguns comandos que trabalham com isso, dentre eles temos o grep -E
ou o egrep
(egrep é similar a grep -E
), o comando sed
também é muito usado com REGEX.
Expressão com colchete
Existe outro tipo de REGEX denominado expressão de colchetes. Embora não sejam um único caractere, os colchetes []
(incluindo seu conteúdo) são considerados uma única REGEX. Uma expressão de colchetes geralmente é apenas uma lista de caracteres literais delimitados por []
, fazendo com que a REGEX corresponda a qualquer caractere único da lista. Por exemplo, a expressão [1b]
pode ser encontrada em strings abcd
e a1cd
. Para especificar caracteres aos quais a REGEX não deve corresponder, a lista deve começar com ^
, como em [^1b]
. Também é possível especificar intervalos de caracteres em expressões de colchetes. Por exemplo, [0−9]
corresponde aos dígitos de 0 a 9 e [a−z]
corresponde a qualquer letra minúscula. Os intervalos devem ser usados com cuidado, pois podem não ser consistentes em locais distintos.
As listas de expressão entre colchetes também aceitam classes em vez de apenas caracteres e intervalos únicos. As classes que vou apresentar se chama POSIX:
POSIX similar Significado
[:upper:] [A-Z] letras maiúsculas
[:lower:] [a-z] letras minúsculas
[:alpha:] [A-Za-z] maiúsculas/minúsculas
[:alnum:] [A-Za-z0-9] letras e números
[:digit:] [0-9] números
[:xdigit:] [0-9A-Fa-f] números hexadecimais
[:punct:] [.,!?:...] sinais de pontuação
[:blank:] [ \t] espaço e TAB
[:space:] [ \t\n\r\f\v] caracteres brancos
[:cntrl:] - caracteres de controle
[:graph:] [^ \t\n\r\f\v] caracteres imprimíveis
[:print:] [^\t\n\r\f\v] qualquer caractere imprimível, até o espaço
Exemplos:
## Exemplo do . (-o no egrep é para mostrar só o que deu match)
# Vamos usar o 'uniq' para remover o que estiver repetido:
$ ls /dev/ | egrep -o "sd." | uniq
sda
sdb
sdc
sdd
# Listar 2 caracteres qualquer com ponto:
$ ls /dev/ | egrep -o "sd.."
sda1
sdb1
sdb2
sdb3
sdb4
sdc1
sdc2
sdc3
sdc4
sdc5
sdc6
sdd1
sdd2
### Vamos usar ^ e o $
# Procurando a plavra root no começo da linha:
$ egrep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
# Procurando a plavra bash no final da linha:
$ egrep bash$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
linux:x:1000:1000:linux,,,:/home/linux:/bin/bash
### Exemplo usando a lista e lista negada
## Crie um arquivo de texto com a saída abaixo:
texto
testo
teto
texo
# Agora vamos usar a lista para procurar por 'texto' e 'testo':
$ grep -E 'te[xs]to' texto
texto
testo
# Agora vamos excluir a palavra escrita errada:
$ grep -E 'te[^s]to' texto
texto
## Usando a chave {}
# A REGEX usa grupo '()', chaves para delimitar a quantidade
# de repetição e lista para delimitar um range de caracteres:
$ ip a | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"
127.0.0.1
192.168.1.3
192.168.1.255
192.168.100.1
192.168.100.255
192.168.122.1
192.168.122.255
Usando o SED
O SED é um editor de fluxo que filtra e transforma texto, fazendo sua alteração/edição. Sua principal função é editar arquivos dinamicamente, o uso de expressão regular dentro do SED o torna uma “linguagem”, deixando esse utilitário muito completo, complexo e poderoso.
Você vai usar muito o SED em script, ele vai facilitar sua vida quando você tiver que alterar um determinado dado ou campo em mais de 50 arquivos diferentes e ele vai fazer isso em apenas alguns segundos.
Esse mini tutorial tem como objetivo apresentar algumas funcionalidade do SED, apenas o básico, trazendo para você o que você irá mais precisar para criar bons scripts, com uma linguagem mais automatizada. Lembrando, para que você domine o SED, é necessário ter conhecimento em expressão regular ou ER como chamamos, nesse mini tutorial não vamos abordar isso, mas em certos casos, vou explicar como funciona o comando usando uma expressão regular ou usando um metacaractere.
Opção | Descrição |
---|---|
-i | Altera o arquivo |
-e | Imprime na tela sem alterar o arquivo |
-n | Faz a supressão, mostra só o resultado do comando |
-r | Informa para o sed usar REGEX |
Comandos | Descrição |
s/// | Substitui um trecho de texto por outro |
! | Inverte a lógica do comando |
; | Separador de comandos |
\ | |
d | No final deleta |
p | No final imprime |
g | No final (como se usa o d e p) altera todas as ocorrências |
q | Sai do SED, não continua o comando |
\L | Turn the replacement to lowercase until a '\U' or '\E' is found |
\l | Turn the next character to lowercase |
\U | Turn the replacement to uppercase until a '\L' or '\E' is found |
\u | Turn the next character to uppercase |
\E | Stop case conversion started by '\L' or '\U' |
Crie o arquivo telefones:
Vitor gerald (011)666-1234
Marcia Dias (011)555-2112
Enzo (012)232-3423
Rodrigo Guetes (022)622-2876
Luiz Rodrigues (026)555-2124
Crie o arquivo telefones_branco:
Vitor gerald (011)666-1234
Marcia Dias (011)555-2112
Enzo (012)232-3423
Rodrigo Guetes (022)622-2876
Luiz Rodrigues (026)555-2124
Exemplos:
### Remover espaços duplicados com SED,
# ' +' faz com que o REGEX pegue um ou mais espaços
$ echo "oi, tudo bem?" | sed -r 's: +: :g'
oi, tudo bem?
### Removendo as linhas em branco (sem alterar o arquivo)
$ sed '/^$/d' telefone_branco
Vitor gerald (011)666-1234
Marcia Dias (011)555-2112
Enzo (012)232-3423
Rodrigo Guetes (022)622-2876
Luiz Rodrigues (026)555-2124
# O circunflexo ^ representa início de uma linha, já o cifrão $
# representa o fim dela, portanto, uma linha em branco tem o
# início junto com o final, sendo assim é só deletar a mesma.
### Usando o operador lógico OU:
$ sed -rn '/Enzo|Vitor|Luiz/p' telefones_branco
Vitor gerald (011)666-1234
Enzo (012)232-3423
Luiz Rodrigues (026)555-2124
# Aqui usamos o | (pipe) e assim podemos colocar múltiplas strings para
# serem pesquisadas e exibidas na tela, isso poupa muito tempo quando
# você precisa pegar mais de um dado.
### Inserir dados no início e fim
$ sed -r 's/2876$/& - desatualizado/' telefones_branco
Vitor gerald (011)666-1234
Marcia Dias (011)555-2112
Enzo (012)232-3423
Rodrigo Guetes (022)622-2876 - desatualizado
Luiz Rodrigues (026)555-2124
# Aqui usei o & (ec comercial), ele meio que faz um append,
# ai usando o sed para inserir o dado.
# Observe que usei 2876$ (2876 no final da linha) e então fiz um
# APPEND depois disso.