Remova as linhas que estão entre os padrões determinados de um arquivo (usando ferramentas Unix)

StackOverflow https://stackoverflow.com/questions/1996585

  •  22-09-2019
  •  | 
  •  

Pergunta

Eu tenho um arquivo de texto (mais corretamente, um arquivo CSV de estilo alemão, ou seja, vírgula decimal e separada por semicolon) que tem uma data e o valor de uma medição em cada linha.
Existem trechos de valores defeituosos que eu quero remover antes de trabalhar mais. Gostaria de armazenar esses cortes em algum script para que minhas correções sejam documentadas e posso reproduzir essas correções, se necessário.

As linhas são assim:

28.01.2005 14:48:38;5,166
28.01.2005 14:50:38;2,916
28.01.2005 14:52:38;0,000
28.01.2005 14:54:38;0,000
(long stretch of values that should be removed; could also be something else beside 0)
01.02.2005 00:11:43;0,000
01.02.2005 00:13:43;1,333
01.02.2005 00:15:43;3,250

Agora eu gostaria de armazenar uma lista de padrões iniciais e finais como 28.01.2005 14:52:38 + 01.02.2005 00:11:43, e o script cortaria as linhas que correspondiam a esses pares iniciais/finais e tudo o que está entre eles.

Estou pensando em invadir um script AWK, mas talvez esteja perdendo uma ferramenta já existente.

Foi útil?

Solução

Dê uma olhada em sed:

sed '/start_pat/,/end_pat/d'

excluirá linhas entre start_pat e end_pat (inclusive).

Para excluir vários pares, você pode combiná -los com múltiplos -e Opções:

sed -e '/s1/,/e1/d' -e '/s2/,/e2/d' -e '/s3/,/e3/d' ...

Outras dicas

Em primeiro lugar, por que você precisa manter um registro do que fez? Por que não manter um backup do arquivo original ou fazer uma diferença entre os arquivos antigos e novos ou colocá -lo em controle de origem?

Para as mudanças reais, sugiro usar o VIM.

O vim :global comando (abreviado para :g) pode ser usado para ser executado: comandos ex em linhas que correspondem a um regex. Isso é, de muitas maneiras, mais poderoso que o AWK, pois os comandos podem se referir a intervalos em relação à linha correspondente, além de você ter o poder de processamento de texto completo do VIM à sua disposição.

Por exemplo, isso fará algo próximo ao que você deseja (não testado, então advertem o Emptor):

:g!/^\d\d\.\d\d\.\d\d\d\d/ -1 write tmp.txt >> | delete

Isso corresponde às linhas que não começam com uma data (o ! nega a correspondência), anexa a linha anterior ao arquivo tmp.txt e exclui a linha atual.

Você provavelmente acabará com linhas duplicadas no tmp.txt, mas elas podem ser removidas executando o arquivo através do Uniq.

você também usa estranho

awk '/start/,/end/' file

Eu sugeriria seriamente aprender o básico de Perl (ou seja, não as coisas do OO). Ele o reembolsará em cargas de balde.

É rápido e simples escrever um pouco de Perl para fazer isso (e muitas outras tarefas dessas) depois de entender os fundamentos, que se você estiver acostumado a usar awk, sed, grep etc, são bem simples.

Você não precisará se lembrar de como usar muitas ferramentas diferentes e onde anteriormente teria usado várias ferramentas para resolver um problema, basta usar um único script Perl (geralmente muito mais rápido para executar).

E o Perl está instalado em praticamente todas as distroções UNIX/Linux agora.

(Esse sed é legal :-)

Use Grep -l (imprimir nenhuma linhas correspondentes)

Desculpe - pensei que você só queria linhas sem 0.000 no final

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top