Como apagar linhas em branco a partir da linha 5

10

Eu tenho isso:

sed -i '/^$/d' temp_spec.rb

que está removendo linhas em branco e funciona bem. Como posso fazer isso apenas para as linhas 5-999 (ou, idealmente, 5 para o fim do arquivo).

Eu tentei:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

mas não funcionou (sem erros).

    
por Michael Durrant 16.05.2013 / 20:46

3 respostas

12

Se você quiser apagar todas as linhas em branco começando com a linha 5 e manter as linhas 1 a 4, você pode usar

sed -i '5,${;/^$/d;}' temp_spec.rb

O { é o operador de agrupamento, portanto, o primeiro comando 5,${ significa "da linha 5 até o final da entrada ( $ ) executar os comandos a seguir até coincidir com } ". Os comandos entre { e } podem ser prefixados novamente por endereços, então o comando interno /^$/d significa "se não houver nada entre início ( ^ ) e fim ( $ ) da linha, exclua ". Comandos Sed podem ser separados por ; . (Esse é um recurso mal documentado do sed. Ele é suportado pela maioria das implementações de sed, mas é não totalmente portáveis .) Como observado por Hauke, o ; after { é opcional; o antes de } é necessário.

Se você quiser excluir todas as linhas em branco começando com a linha 5 e também excluir as linhas de 1 a 4, é mais fácil:

sed -i '1,4d;/^$/d' temp_spec.rb
    
por 16.05.2013 / 20:55
4

Outra opção usando o awk:

awk 'NR<5||/./'
    
por 16.05.2013 / 21:16
2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

Editar 1:

Eu devo explicar isso, assim ...

Isso é desnecessariamente complicado. Eu não sabia que os intervalos de endereços são permitidos em {} . Então eu tive que expressar "excluir linhas vazias" de forma diferente. O comando do núcleo é t , que é o caminho do sed de if ... then . T teria sido mais fácil, mas está disponível apenas para o GNU sed. Cito a man page:

t label : If a s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to label; if label is omitted, branch to end of script.

Eu abusei do famoso comando s . Não substituirá nada, mas testará apenas se a linha está vazia. Por isso, substitui uma linha vazia por uma linha vazia (poderia usar qualquer coisa como substituição, já que a linha é excluída de qualquer maneira).

Se s tiver feito uma "substituição", a linha estará vazia. Nesse caso, o comando d será executado. Caso contrário, nada deve ser feito. Como t não pula no caso de uma ação s , eu preciso do comando de ramificação b para pular para o final do script. : label são destinos de ramificação. Como goto na época das trevas (quando sed foi inventado ... te-hee).

Outra opção seria ter s "substituir" todas as linhas não vazias, tornando o s mais complicado, mas o resto do comando mais fácil:

sed '5,${s/^\(..*\)$//; t end; d; : end;}' input

^..*$ significa "linha não vazia" e significa "o conteúdo dos primeiros colchetes".

    
por 16.05.2013 / 20:56

Tags