Exclui o número desconhecido de linhas, exceto a última linha

2

O bloco sempre começa com:     00 PROGRAMA

e termina com XYZ seguido por uma linha em branco. O XYZ aparece mais cedo também, no bloco de linhas, mas as linhas anteriores são seguidas por mais dados. Eu só preciso da última linha antes da linha em branco. Eu não encontrei nenhum código que parece coincidir com a minha intenção. Espero que esta seja uma resposta fácil para alguém!

Eu quero manter a última linha antes da linha em branco. Por exemplo:

000-12-22
AB1
00   PROGRAM
01   INQUIRY
03   XYZ
04   XYZ
blank line
LINE VALUE
00456

Apenas esta parte deve ser excluída.

00   PROGRAM
01   INQUIRY
03   XYZ
    
por 985ranch 17.08.2016 / 01:01

2 respostas

2

Resposta para a pergunta revisada

Vamos considerar este arquivo de teste;

$ cat File2
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456

Experimente este comando:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x; p; x;}' File2
000-12-22
AB1
04 XYZ

LINE VA

LUE 00456

Responda para a pergunta original

Se eu entendi corretamente, você tem um arquivo que contém grupos de ônus que começam com uma linha contendo 00 PROGRAM e terminam com uma linha em branco e você deseja a linha antes da linha em branco se ela contiver XYZ . Se for esse o caso, tente isto:

sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 

Exemplo

Considere este arquivo de amostra:

$ cat file
00 PROGRAM
some
XYZ discard this
data
XYZ keep this

other
00 PROGRAM
more
XYZ keep this also

end

Isso mantém apenas as linhas XYZ que precedem a linha em branco em um bloco 00 PROGRAM :

$ sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 
XYZ keep this
XYZ keep this also

Alternativa

Talvez você queira manter todas as linhas fora do grupo e também manter a última linha não vazia do grupo, se corresponder a XYZ . Nesse caso:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/!d}' file 
XYZ keep this
other
XYZ keep this also
end
    
por 17.08.2016 / 01:26
2

Esse tipo de intervalo é um caso de uso perfeito para ex . / 269076/135943 "> escrito sobre ex bastante neste site; é facilmente a melhor ferramenta POSIX para edições de arquivos com script.

Comando:

Se houver apenas um bloco que você precisa manipular, use:

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

Se houver vários blocos, use:

printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' x | ex file.txt

Para testes, use %p em vez de x :

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' %p | ex file.txt
printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' %p | ex file.txt

Isso imprimirá todo o buffer, em vez de salvar o conteúdo do buffer de volta no arquivo.

Ilustração:

[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 
[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ 

Explicação e comentários:

Você pode usar ex -c 'editingcommands' filename , mas descobri que cria mais problemas do que resolve: Se um erro for encontrado, ex não será encerrado, mas será interrompido aguardando a entrada do usuário. Além disso, há possíveis problemas de portabilidade ao passar vários comandos para ex , pois os recursos comuns que permitem isso não são garantidos pelo POSIX.

Em vez disso, costumo enviar comandos para ex de printf . Isso permite uma fácil separação de nova linha de vários comandos usando %s\n como a string de formato para printf e deixa o arquivo inalterado se houver um erro, sem ser interrompido (por exemplo, se você tentar editar uma linha maior que a última linha do arquivo).

Para testar um comando antes de realmente editar o arquivo, eu uso %p (print whole buffer) como o último comando. Então eu posso ajustar o comando um pouco e executá-lo de novo e de novo, até obter o conteúdo exato do arquivo que eu quero. Uma vez que estou feliz com o resultado, mudo o %p para x e executo o comando one mais tempo para salvar as alterações no arquivo.

Aqui está novamente o comando que dei como resposta a esta pergunta:

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

O comando printf simplesmente imprime as três strings /00 PROGRAM/ , .,/^$/-2d e x separadas por novas linhas, assim:

[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x
/00 PROGRAM/
.,/^$/-2d
x
[vagrant@localhost ~]$ 

Essas três linhas são ex de comandos.

Uma visão geral dos comandos ex

Um comando ex tem duas partes: um endereço (baseado em linha) e um comando.

Se houver apenas um endereço, o cursor se moverá para esse endereço (mova para essa linha).

Se houver apenas um comando, a linha atual é usada como endereço.

Um endereço geralmente pode ser um intervalo : um endereço, seguido por uma vírgula, seguido por outro endereço. Isso se refere a todas as linhas do primeiro endereço até o segundo endereço.

Um endereço pode ser um número de linha, mas não precisa ser. Também pode ser um padrão de pesquisa que significa "A próxima linha depois da linha atual que corresponde a esta regex". Você pode fazer pesquisas para trás e encaminhar pesquisas.

Você pode até escrever um endereço que significa "Duas linhas antes da instância de foo que ocorre logo após a instância de bar que precede mais imediatamente a linha atual". Isso seria parecido com: ?bar?/foo/-2

Passo a passo

O comando /00 PROGRAM/ é apenas um endereço, por isso significa "mover o cursor para a primeira instância do padrão '00 PROGRAM '".

O comando .,/^$/-2d tem duas partes. O d no final é o comando, que significa "excluir". O resto é o endereço.

A porcentagem inicial% co_de é um endereço especial que se refere à linha atual.

O padrão . é uma expressão regular para uma linha vazia (início da linha /^$/ seguido imediatamente pelo fim da linha ^ ). Neste caso, significa a próxima linha vazia após a posição atual do cursor.

O $ significa "duas linhas de volta".

Todos juntos, então, -2 significa: "Apague as linhas da linha atual para a linha duas linhas acima da próxima linha vazia."

.,/^$/-2d significa simplesmente salvar o conteúdo do buffer no arquivo e sair do editor.

Espero que você ache isso útil. x é uma ferramenta extremamente poderosa para edição de texto. É o antecessor imediato de ex , que é o "editor visual". Todos os comandos vi podem ser executados em ex também.

    
por 17.08.2016 / 02:53

Tags