Adicionando uma linha de texto a vários arquivos


10

Portanto, tenho vários arquivos em um diretório e preciso inserir uma linha de texto em cada um deles. Eles têm essencialmente o seguinte formato:


<VirtualHost *:80>
        ServerAdmin gabe@localhost
        DocumentRoot /var/www/test1
        ServerName test1.local
        ServerAlias test1
        <Directory "/var/www/test1">
                Options All
                AllowOverride All
        </Directory>
</VirtualHost>

E eu gostaria de inserir uma linha antes do fechamento

</VirtualHost>
tag. Minha primeira suposição é que eu deveria ser capaz de fazer isso com o sed, provavelmente combinando e substituindo essa tag. Vou começar a tentar isso agora, mas se alguém já tiver uma maneira de fazer isso, eu adoraria ouvir.


Serei honesto quando digo que acho que isso é mais uma tarefa de programação ... e, portanto, deve estar no SO. Eu usaria o Perl para fazer isso, especialmente porque aposto que existe um módulo perl projetado para analisar e modificar as configurações do apache.
Xenoterracide

2
Obrigado, mas é uma tarefa que deve ser fácil de realizar com ferramentas simples do unix, portanto, solicitadas aqui. Obrigado pelo seu comentário, no entanto.
Gabe.

Respostas:


10

Algo assim:

sed 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/'

trabalho. Se você deseja repetir este comando em muitos arquivos, pode fazer algo como:

for i in *; do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' "$i"; done

Provavelmente melhor (mas não testado) graças a @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\
do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' $filename;\ 
done

incrível ... é exatamente isso que eu estava procurando.
Gabe.

1
Você não analisar ls. Use um globo em seu lugar. mywiki.wooledge.org/ParsingLs
Chris Down

Você é o @ChrisDown. Por favor, melhore minha resposta.
23811 lcipriani

Escolhendo um personagem diferente /para a expressão sed é mais limpa, desde que você não tem que escapar do golpe:'s:</VirtualHost>:yourlinehere\n</VirtualHost>:'
Alexander

2

Se você não se importa com o Perl, tente:

perl -pi'*.old' -e 's(</VirtualHost>(Your stuff here\n</VirtualHost>)' myfile

A -iopção salvará seu arquivo antigo com uma .oldextensão e será impresso no atual.


2

Você também pode usar "ex" (linha de comando vi) se a edição que você deseja fazer for um pouco complicada. Por exemplo, você deseja fazer a inserção apenas em uma instância de "".

Um script de shell como este pode funcionar:

for FILENAME in *.whatever  # Need a criteria to glob, or a list of names
do
    ex -s $FILENAME << END_EDITS
/^<\/VirtualHost>/
O " capital-o, not zero
text to insert goes here
.
w!
q
END_EDITS
done

Essa abordagem oferece as vantagens de "ex": encontrar um local com padrões elaboarte e 'movimentos do cursor'. Você pode fazer coisas como encontrar um padrão e, em seguida, encontrar a próxima instância, ENTÃO faça a inserção. Ou você pode alterar o texto, em vez de apenas fazer inserções. Ou você pode mudar entre os intervalos. Não esqueça que "ex" permite que você use "." como a linha atual, portanto, / ^ somepatter / s / blah / foo / funcionará.


0

Você pode usar o seguinte código de linha única para inserir uma única linha ou várias linhas em um determinado local em um arquivo, no seu caso antes de 'VirtualHost'. O código basicamente procura o nome do arquivo (pode ser *. *, Se você quiser inserir os textos em todos os arquivos) dentro do diretório especificado e de seus subdiretórios. Nos arquivos encontrados, ele procura o padrão 'VirtualHost'. Depois de encontrar o padrão, ele o substitui por firstline \ nsecondline \ notherlines \ n \ VirtualHost. Observe que 'VirtualHost' faz parte do texto para substituição, caso contrário, o perderemos.

find directory/ -name filename -print | xargs sed -i 's|VirtualHost|firstline\nsecondline\notherlines\nVirtualHost|g'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.