Substitui ou acrescenta uma linha com string dentro de um arquivo

4

Estou procurando conselhos sobre como pesquisar uma parte de uma string dentro de um arquivo e substituir a linha completa OU acrescentar essa string a esse arquivo, se não for encontrado. Eu "joguei" com sed por um tempo agora, mas não consegui fazê-lo funcionar como esperado.

Eu preciso adicionar:

/swapfile   none    swap    sw    0   0

para /etc/fstab (em Ubuntu 14.04 - Trusty Tahr ).

Condições:

  • Se qualquer linha que comece com /swapfile estiver presente em /etc/fstab , remova essa linha e substitua-a pela string fornecida acima
  • Se mais de uma linha que começa com /swapfile for encontrada, remova-as todas e anexe a sequência acima ao final do arquivo
  • Se não houver /swapfile em /etc/fstab , anexe a sequência a /etc/fstab
  • O comando não deve mostrar a saída do console e deve ser um "one-liner" (devido a propósitos de automação com o fantoche)

Estou confiante de que isso é possível, mas simplesmente não encontrei um tutorial relacionado sobre o uso do sed da maneira que eu preciso.

Eu usei sudo sed -i '$a/swapfile none swap sw 0 0' /etc/fstab , mas isso só acrescenta a string: (

    
por frank 20.12.2014 / 21:55

2 respostas

5

Você pode fazer isso com sed - é Turing-complete. Mas não é a melhor ferramenta para o trabalho. Sed não tem uma maneira conveniente de lembrar que já foi feito um substituto.

O que você pode fazer relativamente facilmente com o sed é colocar todas as linhas em branco iniciando /swapfile e adicionar uma nova no final:

sed -i '$! s/^\/swapfile[\t ]//; $s/\(^\/swapfile.*\)\?$/\n\/swapfile none swap sw/' /etc/fstab

mas além disso, estamos entrando rapidamente em um território onde eu não deixaria esse código sed para outro administrador de sistema manter, especialmente quando uma combinação simples e legível de comandos de shell faria um trabalho melhor:

{ </etc/fstab grep -v '/swapfile[\t ]'; echo '/swapfile none swap sw'; } >/etc/fstab.new && mv /etc/fstab.new /etc/fstab

Se você quiser preservar a posição existente da linha /swapfile se ela estiver lá e apenas modificar o arquivo se precisar ser modificado, uma combinação de lógica shell e awk é uma ferramenta melhor. Eu usei várias linhas aqui para maior clareza, mas você pode colocar todo o código na mesma linha, se quiser. Como bônus, se o arquivo já continha a linha desejada (com espaçamento exato), ele não será modificado.

awk '
  /\/swapfile[\t ]/ {if (replaced) {next}
                     else {replaced=1; print "/swapfile none swap sw"}}
  1 {print}
  END {if (!replaced) print "/swapfile none swap sw"}
' /etc/fstab >/etc/fstab.new &&
if cmp -s /etc/fstab.new /etc/fstab.new; then
  rm /etc/fstab.new;
else
  mv /etc/fstab.new /etc/fstab;
fi
    
por 20.12.2014 / 22:44
4

Como você está automatizando isso com o Puppet, é melhor deixar o Puppet lidar com fstab para você. Use o tipo de recurso de montagem .

Algo como:

mount{'swapfile':
    name    => 'none',
    fstype  => 'swap',
    ensure  => mounted,
    atboot  => true,
    device  => '/swapfile',
    options => 'sw',
}

deve funcionar.

Se isso absolutamente tem que ser feito com um one-liner (que, para o registro, Ainda sou contra ), o seguinte perl deve ajudar:

perl -pi -e 'BEGIN{$string = "/swapfile   none    swap    sw    0   0"} s!^/swapfile.*!$string! && $x++;END{print "$string\n" unless $x}' /etc/fstab

dividido em várias linhas para maior clareza:

perl -pi -e '
             BEGIN{$string = "/swapfile   none    swap    sw    0   0"}
             s!^/swapfile.*!$string! && $x++; # Modify line if it exists
             END{print "$string\n" unless $x} # Append it if it wasn't found
            ' /etc/fstab
    
por 20.12.2014 / 22:12