Com Terminal: Usando Expressões Regulares II: Substituições

Em mim artigo anterior Eu disse a você em um nível básico como funciona cada um dos caracteres especiais mais usados ​​de expressões regulares. Com essas expressões regulares, é possível fazer pesquisas complexas em arquivos de texto ou na saída de outros comandos. Neste artigo, irei explicar como usar o comando sed para localizar e substituir texto de uma forma muito mais poderosa do que simplesmente trocar um texto por outro.

Um pouco mais sobre o comando grep

Antes de começar a falar sobre sed, gostaria de comentar um pouco mais sobre o comando grep para completar um pouco o que foi explicado no artigo anterior. Tudo o que vou dizer também será relevante para este. Mais tarde veremos a relação entre isso e as pesquisas.

Combinando expressões regulares

Muitos dos caracteres especiais sobre os quais falei no artigo anterior podem ser combinados, não apenas com outros caracteres, mas com expressões regulares inteiras. A maneira de fazer isso é usar parênteses para formar uma subexpressão. Vamos ver um exemplo disso. Vamos começar baixando um texto que podemos usar para teste. É uma lista de frases. Para isso vamos usar o seguinte comando:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Isso deixará você no diretório onde você inicia um arquivo com o nome “frases”. Você pode abri-lo para dar uma olhada e rir um pouco. 

Agora vamos supor que queremos encontrar as frases que têm exatamente 6 palavras. A dificuldade está em formar uma expressão regular que corresponda a cada palavra. Uma palavra é uma sequência de letras, maiúsculas ou minúsculas, que seria algo como '[a-zA-Z]+', mas você também deve especificar que essas letras devem ser separadas por outros caracteres que não letras, ou seja, seria algo como '[a-zA-Z]+[^a-zA-Z]+'. Vamos lembrar: o "^" como o primeiro caractere dentro dos colchetes indica que queremos corresponder a caracteres que não estão nos intervalos e o "+" indica 1 ou mais caracteres.

Já temos uma expressão regular que pode corresponder a uma palavra. Para emparelhar com 6, terá que ser repetido 6 vezes. Para isso usamos as chaves, mas é inútil colocar '[a-zA-Z]+[^a-zA-Z]+{6}', porque o 6 repetiria a última parte da expressão regular e o que queremos é repetir tudo, então o que você tem que colocar é o seguinte: '([a-zA-Z]+[^a-zA-Z]+){6}'. Com os parênteses formamos uma subexpressão e com as chaves repetimos 6 vezes. Agora você só precisa adicionar um "^" na frente e um "$" atrás para corresponder a toda a linha. O comando é o seguinte:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

E o resultado é exatamente o que queríamos:

É mais cantada que a Macarena. Você está mais acabado do que Luis Aguilé. Você tem menos cultura do que uma pedra. Você conhece mais línguas do que Cañita Brava. Ele tem mais rugas do que Tutan Khamón. Você sabe menos do que Rambo sobre cuidados infantis.

Observe que colocamos o parâmetro -E porque queremos usar expressões regulares estendidas para fazer o "+" funcionar. Se usarmos os básicos, teríamos que escapar dos parênteses e das chaves.

Referências anteriores ou referências anteriores

Se você tiver um corretor ortográfico instalado, provavelmente terá uma lista de palavras em /usr/share/dict/words. Caso contrário, você pode instalá-lo no arch com:

sudo pacman -S words

Ou em debian com:

sudo aptitude install dictionaries-common

Se você quiser, pode dar uma olhada no arquivo para ver quais palavras ele contém. Na verdade, é um link para o arquivo word do idioma em que sua distribuição está. Você pode ter vários arquivos de texto instalados ao mesmo tempo.

Vamos usar esse arquivo. Acontece que estamos muito curiosos para conhecer todos os palíndromos de sete letras que existem. Para quem não sabe: Palíndromo é uma palavra capicúa, ou seja, pode ser lida da esquerda para a direita e também da direita para a esquerda. Vamos tentar o seguinte comando:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Parece um pouco estranho, certo? Se tentarmos, o resultado dependerá do idioma de sua distribuição e das palavras de sua lista, mas no meu caso, com o idioma espanhol, o resultado é o seguinte:

anilina anilina rolando

Vamos ver como funciona essa expressão regular.

Além do "^" e do "$", que já sabemos para que servem, a primeira coisa que vemos à esquerda são três grupos de pontos entre parênteses. Não se confunda com as barras na frente de cada parêntese. Eles devem escapar dos parênteses porque estamos usando expressões regulares básicas, mas eles não têm outro significado. O importante é que estamos solicitando quaisquer três caracteres com os pontos, mas cada um desses pontos está entre parênteses. Isso serve para salvar os caracteres que correspondem a esses pontos para que possam ser referenciados novamente a partir da expressão regular. Este é outro uso de parênteses que será útil posteriormente para fazer substituições.

É aqui que os três números abaixo vêm com a barra na frente deles. Nesse caso, a barra é importante. É usado para indicar que o número abaixo é uma referência anterior e se refere a um dos parênteses anteriores. Por exemplo: \ 1 refere-se ao primeiro parêntese, \ 2 ao segundo e assim por diante.

Ou seja, com a expressão regular que colocamos, o que estamos procurando são todas as palavras que começam com quaisquer quatro letras e depois têm uma letra igual à terceira, outra igual à segunda e outra igual à primeiro. O resultado são os palíndromos de sete letras que estão na lista de palavras. Exatamente como queríamos.

Se estivéssemos usando expressões regulares estendidas, não teríamos que escapar dos parênteses, mas com expressões regulares estendidas, as referências anteriores não funcionam em todos os programas porque não são padronizadas. No entanto, com o grep eles funcionam, então essa pode ser outra maneira de fazer o mesmo. Você pode tentar se quiser.

Expressões de substituição: o comando sed

Além de pesquisar, um dos melhores usos das expressões regulares é substituir textos complexos. Para fazer isso, uma maneira de fazer isso é com o comando sed. O poder do comando sed vai muito além de substituir texto, mas aqui vou usá-lo para isso. A sintaxe que vou usar com este comando é a seguinte:

sed [-r] 's/REGEX/REPL/g' FICHERO

Ou também:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Onde REGEX será a expressão regular de pesquisa e REPL a de substituição. Tenha em mente que este comando não substitui realmente nada no arquivo que indicamos, mas o que ele faz é nos mostrar o resultado da substituição no terminal, então não se assuste com os comandos que irei colocar a seguir. Nenhum deles vai modificar nenhum arquivo em seu sistema.

Vamos começar com um exemplo simples. Todos nós temos vários arquivos de configuração no diretório / etc que geralmente têm comentários que começam com "#". Suponha que desejamos ver um desses arquivos sem os comentários. Por exemplo, vou fazer isso com o fstab. Você pode tentar com o que quiser.

sed 's/#.*//g' /etc/fstab

Não vou colocar aqui o resultado do comando porque depende do que você tem em seu fstab, mas se você comparar a saída do comando com o conteúdo do arquivo você verá que todos os comentários desapareceram.

Neste comando, a expressão de pesquisa é «#.*", Isso é um" # "seguido por qualquer número de caracteres, ou seja, os comentários. E a expressão de substituição, se você olhar as duas barras seguidas, verá que não há nenhuma, então o que ela está fazendo é substituir os comentários por nada, ou seja, excluí-los. Simplesmente impossível.

Agora vamos fazer o oposto. Suponha que o que queremos é comentar em todas as linhas do arquivo. Vamos tentar assim:

sed 's/^/# /g' /etc/fstab

Você verá que, na saída do comando, todas as linhas começam com uma marca de hash e um espaço em branco. O que fizemos foi substituir o início da linha por «# «. Este também é um exemplo bastante simples onde o texto a ser substituído é sempre o mesmo, mas agora vamos complicar um pouco mais.

A graça das substituições é que, na expressão de substituição, você pode usar referências anteriores como as que eu disse antes. Vamos voltar ao arquivo de frase que baixamos no início do artigo. Vamos colocar entre parênteses todas as letras maiúsculas que existem, mas faremos isso com um comando:

sed 's/\([A-Z]\)/(\1)/g' frases

O que temos aqui é uma referência anterior na expressão de substituição que se refere aos parênteses na expressão de pesquisa. Os parênteses na expressão de substituição são parênteses normais. Na expressão de substituição, eles não têm nenhum significado especial, são colocados como estão. O resultado é que todas as letras maiúsculas são substituídas pela mesma letra, seja ela qual for, com parênteses ao redor.

Há outro caractere que também pode ser usado na expressão de substituição, é "&" e é substituído por todo o texto que corresponde à expressão de pesquisa. Um exemplo disso seria colocar todas as frases do arquivo entre aspas. Isso pode ser feito com este comando:

sed 's/.*/"&"/g' frases

A operação deste comando é muito semelhante ao anterior, só que agora o que substituímos é a linha inteira com a mesma linha com aspas ao redor. Como estamos usando "&", não é necessário colocar parênteses.

Alguns comandos úteis com expressões regulares

Aqui estão alguns comandos que considero úteis ou curiosos e que usam expressões regulares. Com esses comandos, a utilidade das expressões regulares é muito melhor do que com os exemplos que dei até agora, mas me pareceu importante explicar algo sobre como as expressões regulares funcionam para entendê-las.

  • Mostrar seções de uma página de manual:

man bash | grep '^[A-Z][A-Z ]*$'

Claro, você pode alterar o comando bash para o que quiser. E então do homem, você pode ir diretamente para a seção que lhe interessa usando, é claro, uma expressão regular. Pressione «/» para começar a pesquisar e escrever «^ALIASES$»Para ir para a seção ALIASES, por exemplo. Acho que esse é o primeiro uso que comecei a fazer das expressões regulares há alguns anos. Percorrer algumas páginas do manual é quase impossível sem um truque como este.

  • Mostre os nomes de todos os usuários da máquina, incluindo os especiais:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Mostrar nomes de usuário, mas apenas aqueles com shell:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Isso realmente pode ser feito com uma única expressão regular, mas a maneira de fazer isso vai além do que eu disse a você nestes artigos, então fiz isso combinando dois comandos.

  • Insira uma vírgula antes dos últimos três dígitos de todos os números no arquivo de números:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Funciona apenas com números de até 6 dígitos, mas pode ser iniciado mais de uma vez para colocar os separadores nos outros grupos de três dígitos.

  •  Extraia todos os endereços de e-mail de um arquivo:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Separe o dia, mês e ano de todas as datas que aparecem em um arquivo:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Descubra nosso IP local:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Isso também pode ser feito com um único comando sed, mas é melhor separá-lo em um grep e um sed para simplificar.

Alguns endereços úteis

Aqui estão alguns endereços que podem ser úteis relacionados a expressões regulares:

  • Biblioteca de expressão regular: É uma biblioteca de expressões regulares na qual você pode pesquisar por expressões regulares relacionadas ao tema que lhe interessa. Para pesquisar endereços da web, ID ou qualquer coisa.
  • REGEXR: Um verificador de expressão regular online. Ele permite que você insira um texto e aplique uma expressão regular para pesquisar ou substituir. Ele fornece informações sobre a expressão regular e você tem algumas opções para alterar seu comportamento.
  • Testador de expressões regulares: É um addon para o firefox que permite verificar as expressões regulares do navegador.

Conclusão

Por enquanto, isso é tudo. As expressões regulares são complexas, mas úteis. Leva tempo para aprendê-los, mas se você for como eu, brincar com eles vai parecer divertido e, aos poucos, você vai dominá-los. É um mundo inteiro. Ainda há muito a dizer sobre quantificadores preguiçosos, regex estilo PERL, multilinha, etc. E cada programa tem suas características e suas variantes, então o melhor conselho que posso dar é sempre olhar para a documentação do programa que você está usando toda vez que precisar escrever uma expressão regular em um novo programa.

Ei! …EI! …ACORDAR! …O QUE VOCÊS ESTÃO FAZENDO ENQUANTO DORMEM? 

Fontes

Algumas das ideias e exemplos para expressões regulares neste artigo que tirei daqui:


Adicionar como fonte preferencial