Exclua várias linhas do arquivo quando o texto for encontrado

4

Eu já vi várias respostas para excluir uma única linha com sed ou grep , mas preciso pesquisar uma linha, excluí-la e as duas continuações. Por exemplo, no arquivo ~/.profile eu tenho linhas como:

#Set environment variable
export NAME=value
# (blank line here)

Por isso, gostaria de pesquisar #Set environment variable , excluí-la e excluir a próxima linha export NAME=variable (o conteúdo não deveria importar) e a seguinte linha em branco. Os nomes das variáveis export são dinâmicos, mas o comentário será sempre o mesmo. Pode haver outras variáveis export sem o comentário acima que não desejo excluir.

Como posso conseguir isso?

    
por Chris G 17.06.2015 / 16:38

3 respostas

3

Com a versão mais recente do GNU sed (vem com o Ubuntu), você pode combinar literalmente as novas linhas:

sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt
    A opção
  • -z tratará as linhas de arquivos de entrada como terminadas por ASCII NUL em vez de novas linhas, portanto, podemos usar \n para corresponder às novas linhas

  • #Set environment variable\n corresponderá à primeira linha (com nova linha)

  • export [^\n]\+\n corresponderá à segunda linha que começa com export

  • Como a terceira linha está em branco, basta \n fazer

  • Em seguida, substituímos o padrão inteiro correspondido com em branco para manter a parte desejada

Você quer sobrescrever o arquivo com o conteúdo modificado:

sed -zi.bak 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt

O arquivo original será mantido como file.txt.bak , se você não quiser usar apenas sed -zi .

Aqui está um teste:

$ cat file.txt 
#Set environment variable
export NAME=value
#some text

#Set environment variable
export NAME=value

check
value

export some=value

#Set environment variable
export NAME=value

foo bar



$ sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt 
#Set environment variable
export NAME=value
#some text

check
value

export some=value

foo bar
    
por heemayl 17.06.2015 / 16:55
2

É muito fácil fazer isso com o comando delete do sed padrão:

cp ~/.profile ~/.profile.bak
sed '/#Set environment variable/,+2 d' <~/.profile.bak >~/.profile

Cuidado com seu ~ / .profile

    
por ludvik02 17.06.2015 / 18:20
0

Embora sua pergunta pareça que você está procurando uma forma de linha de comando para fazer isso, se eu estivesse em sua situação e só quisesse fazer isso para um ou dois arquivos, usaria emacs .

emacs tem a capacidade de aprender uma sequência de pressionamentos de teclas e depois repeti-las quantas vezes quiser. Então, no seu caso eu abriria ~/.profile em emacs e então digitar

C-x ( C-s #Set environment variable C-a C-k C-k C-k C-x )

[que, em palavras, faz isto: Cx (significa "comece a aprender isto"; Cs significa "procurar por", então procuramos pela variável de ambiente #Set, e então Ca significa "de volta ao começo da linha" , e os três Ck's significam "delete this line", e finalmente Cx) significa "parem de aprender isso".]

Depois que esses comandos foram digitados uma vez, o emacs excluiu três linhas, mas também aprendeu como fazer isso de cor, então agora você pode digitar

C-x e

e ele fará isso novamente ou

C-u 100 C-x e

e ele fará 100 vezes (ou pare quando não conseguir mais linhas com "#Set environment variable").

A vantagem de usar o emacs é que você pode ver suas edições acontecendo "ao vivo" e para uma pessoa paranóica como eu, que tem medo de que um erro de digitação possa excluir muitas coisas que eu não queria excluir, isso me faz muito mais feliz [no momento em que as coisas dão errado no emacs você pode simplesmente retroceder e corrigi-las com C-_ ].

    
por Yannick 17.06.2015 / 16:57