como posso mover linhas em arquivos de texto múltiplos? [duplicado]

1

Oi, suponhamos que eu tenha arquivos semelhantes:

x
x
x
A
B
C
1
2
3
D
E
F
x
x
x

e o que precisa dos arquivos para se parecer:

x
x
x
A
B
C
D
E
F
1
2
3
x
x
x

Sei que posso fazer isso com algumas sed -i s/search/replace/g linhas, mas estou querendo saber se existe uma maneira melhor e mais fácil de mover x number de linhas por y números em qualquer direção?

    
por cerr 15.10.2018 / 23:14

2 respostas

3

ed

echo -e '7,9m12\n,p' | ed -s file.txt
    
por 15.10.2018 / 23:38
3

Usando sed (movendo linhas para baixo, porque é mais fácil com editores de fluxo):

$ sed '7,9{H;d;}; 12{G;s/\n//;}' <file
x
x
x
A
B
C
D
E
F
1
2
3
x
x
x

Você pode ler o script sed como "mover as linhas de 7 a 9 para depois da linha 12".

O script anotado:

7,9{            # These are the lines we'd like to move
    H;          # Append them to the hold space (separated by newlines)
    d;          # Delete from pattern space, start next cycle
}
12{             # This is where we'd like to move those lines
    G;          # Append the hold space
    s/\n//;     # Remove the newline that the above command inserted
}
                # (implicit print)

Como as linhas podem ser endereçadas por expressões regulares (não apenas números de linhas), o seguinte também funcionaria (nesses dados específicos):

sed '/^1/,/^3/{H;d;}; /^F/{G;s/\n//;}' <file

Ou seja, "mova as linhas da linha inicial com 1 até a que começa com 3 até depois da linha que começa com F ".

Uma tradução direta do acima em awk :

awk '/^1/,/^3/ { hold = hold ORS $0; next }
     /^F/      { $0 = $0 hold }
               { print }' <file

Usando "números de linha" (números de registro em awk ):

awk 'NR == 7, NR == 9 { hold = hold ORS $0; next }
     NR == 12         { $0 = $0 hold }
                      { print }' <file

A condição NR == 7, NR == 9 também pode ser escrita em NR >= 7 && NR <= 9 .

Para ser 100% fiel ao código sed , o segundo bloco deve ler { $0 = $0 ORS hold; sub(ORS, "", $0) } , mas é um pouco tolo inserir o separador de registro de saída (uma nova linha por padrão) apenas para removê-lo imediatamente depois.

Para substituir o arquivo original pelo resultado dos comandos acima:

sed ...as above... <file >newfile && mv newfile file

ou a mesma coisa com o comando awk .

Isso deixaria o arquivo original inalterado se o arquivo de entrada de sed / awk não pudesse ser lido ou se o arquivo de saída não pudesse ser gravado.

    
por 15.10.2018 / 23:50