Como posso apagar todas as linhas desordenadas de um arquivo de texto?

5

Visão geral

Considere uma lista ordenada intercalada com elementos não ordenados, por exemplo:

Alligator
Ant
Falcon <--
Baboon
Badger    
Armadillo <--
Caiman
Cat

Como essa lista pode ser processada para que todos os elementos não-ordenados sejam excluídos? Por exemplo:

Alligator
Ant
Baboon
Badger    
Caiman
Cat

Mais algumas informações

Os elementos não ordenados são sempre singulares, os elementos ordenados vêm em grupos de pelo menos 2 linhas. O padrão geral seria:

ordered
ordered
ordered
unordered <--
ordered
ordered
unordered <--
ordered
ordered

Os elementos não ordenados podem ser menores ...

A
B
F <---
D
E

... e superior ao seguinte elemento ordenado:

A
C
B <---
D
E

Para tornar as coisas ainda mais difíceis: os elementos podem ser maiúsculos e minúsculos e conter diacríticos (por exemplo: ä, ö, à).

Existe alguma maneira de conseguir isso com o bash?

    
por Glutanimate 27.02.2014 / 18:42

2 respostas

5

Isso funciona se a última linha estiver correta:

awk 'BEGIN {IGNORECASE=1}; NR==1 {lastline=$0; next;}; {if($0>lastline) {print lastline; '\
'lastline2=lastline; lastline=$0;} else if ($0>lastline2) lastline=$0; }; '\
'END {print lastline;}' file1.txt

versão antiga (com erros, para comparação)

awk 'BEGIN {IGNORECASE=1}; NR==1 {lastline=$0; next;}; '\
'{if($0>lastline) print lastline; lastline=$0;}; END {print lastline;}' file
    
por 27.02.2014 / 19:44
4

Solução da Shell:

#!/bin/bash

IFS=
before=
read -r current

while read -r after
do
  [[ "$before" < "$current" || "$before" = "$current"  ]] &&
    [[ "$current" < "$after" || "$current" = "$after"  ]] &&
    printf '%s\n' "$current" &&
    before="$current"

  current="$after"
done

[[ "$before" < "$current" || "$before" = "$current"  ]] &&
  printf '%s\n' "$current"

Uso: ./script <input_file

Note que com bash você pode usar as comparações [[..]] para as comparações lexicais serem dependentes de local e menos ingênuas (devem funcionar com ä, ö, à etc).

Com referência ao ponto de Stephane sobre como decidir o último exemplo da questão, isso dá preferência à ocorrência posterior. Então, ele realmente removerá C .

    
por 27.02.2014 / 20:00