Inserção no início do arquivo com ‘sed’

incluir_sed-1_abertura

Bem. para inserir conteúdo no final de um arquivo já existente basta redirecioná-lo utilizando o “>>”, isto é, utilizar comandos como «echo “mensagem” >> arquivo1» ou então «cat arquivo2 >> arquivo1» para realizar a tarefa. Mas como fazer o oposto? Isto é, inserir conteúdo no início sem necessariamente criar um arquivo intermediário no processo? Uma maneira de fazê-lo é utilizando o sed.

Inserindo uma linha

Começando com um programa para servir de exemplo, o “count_ff.py”:

for i in range(256):
    print("\x1b[38;2;{};{};{}m{:02x}".format(255-i,i,i,i), end="")
print("\x1b[0m")

Justamente pela falta do Sha-Bang¹ — o tal do “#!” — na primeira linha do arquivo ele acaba não sendo identificado corretamente pelo sistema:

$ chmod +x count_ff.py 
$ ./count_ff.py
./count_ff.py: linha 1: erro de sintaxe próximo ao token inesperado `('
./count_ff.py: linha 1: `for i in range(256):'
$ file count_ff.py 
count_ff.py: ASCII text

Daí, para acrescentar a linha contendo o cabeçalho, basta fazer:

$ sed -i '1 i#!/usr/bin/env python3' count_ff.py

O parâmetro “-i” (ou “- -in-place”) diz ao sed para modificar arquivo usado na entrada² e o resto significa, literalmente, na linha 1, inclua o texto “#!/usr/bin/env python3” — a quebra de linha é automática.

E pronto…

$ file count_ff.py 
count_ff.py: Python script, ASCII text executable
$ ./cont_ff.py
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243
4445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465
666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687
88898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9
aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacb
cccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebeced
eeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfef

Muito trabalho para algo tão simples? Bastava abrir um editor de textos e inserir manualmente? Exatamente, mas pense em como incluir manualmente este mesmo cabeçalho, ou qualquer outro conteúdo, em uma dezena de arquivos! 🙂

(¹) Também desconhecia o nome que vem da contração de sharp (“#”) e bang (“!”).

(²) Precisando apenas testar o resultado final, basta omiti-lo para ter o resultado na saída padrão.

Inserindo um arquivo inteiro

Utilizando a mesma lógica é possível acrescentar, ao invés de uma linha, um arquivo inteiro. Como, por exemplo, adicionar o cabeçalho com a licença do código em todos arquivos de um projeto.

A primeira coisa a fazer é criar o tal cabeçalho da licença, neste exemplo um trecho da mensagem da GPLv3.

$ cat >gpl.txt <<EOT
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
EOT

Sei que faltam nome do programa, descrição e autor mas isto é só um exemplo! 😀

Aqui usa-se o comando “r” para inserir o arquivo “gpl.txt” logo após a linha 1 — um pouco de atenção por difere do “i” que faz a inserção no começo da linha.

$ sed -i "1 r./gpl.txt" count_ff.py

Como resultado final…

$ cat count_ff.py
#!/usr/bin/env python3
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
for i in range(256):
    print("\x1b[38;2;{};{};{}m{:02x}".format(255-i,i,i,i), end="")
print("\x1b[0m")

E , pronto, o arquivo com o licenciamento devidamente inserido no arquivo.

Para finalizar

Este é um exemplo interessante de uso do sed para a modificação do conteúdo de arquivos, algo bem diferente do trivial (e quase obrigatório de se conhecer) ‘s/«de»/«para»/g’. Aliás, na documentação oficial, as opções “i” e “r” encontram-se listadas justamente no capítulo sobre os comandos pouco utilizados. 🙂

 

Anúncios