Estou tentando alterar a ordem das linhas em um padrão específico. Trabalhando com um arquivo com muitas linhas (por exemplo, 99 linhas). Para cada três linhas, gostaria que a segunda linha fosse a terceira linha e a terceira a segunda.
EXEMPLO.
1- Entrada:
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...
2- Saída:
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...
linux
text-processing
command-line
Annick Raymond
fonte
fonte
NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.Ou seja,
p
limpe a linha atual, obtenha an
ext,h
antiga, obtenha an
extG
e a linha retida (anexa ao espaço do padrão) ep
limpe esse espaço de padrão de 2 linhas com a terceira e a segunda linhas trocadas.fonte
Outra abordagem inábil :
A saída:
(getline L2)>0 && (getline L3)>0
- extrai os próximos 2 registros, se existiremcada segundo e terceiro registros são atribuídos
L2
eL3
variáveis respectivamentefonte
line2
etc.Usando
perl
e um script curto:O script processa o arquivo inteiro. Para cada linha (armazenada em
$_
), ela obtém as próximas duas linhas ($l2
e$l3
) e as imprime na ordem solicitada: linha1, linha3, linha2.fonte
Uma maneira pode ser a seguinte:
Alternativamente,
Resultados
fonte
Por que não fazer um loop while? Em forma expandida:
No "formato de linha única":
Saídas:
fonte
Perl
A idéia aqui é que usamos o operador módulo
%
com$.
variável de número de linha , para descobrir qual é o primeiro, qual é o segundo e qual é a terceira linha. Para cada terceira linha, o restante é 0, enquanto para cada primeira e segunda linhas, ele terá números correspondentes.Teste:
Melhoria menor
A abordagem para armazenar a segunda linha em uma variável tem uma falha. E se a última linha for a "segunda", ou seja, para o número restante da linha for 2? O código original da minha resposta e da DopeGhoti não será impresso
My dog is orange
se deixarmos de fora a última linha. A correção para isso em ambos os casos é usar oEND{}
bloco de código, desabilitando a variável temporária após a impressão. Em outras palavras:e
Dessa forma, o código funcionará para um número arbitrário de linhas em um arquivo, não apenas para as divisíveis por 3.
Correção adicional para o problema mencionado nos comentários
No caso do awk, se a última linha do arquivo produzir uma saída de 1 por $. % 3, o código anterior tem o problema de gerar nova linha em branco devido à impressão incondicional de
END{print delay}
, uma vez que aprint
função mencionada nos comentários sempre anexa nova linha a qualquer variável em que esteja operando. No caso daperl
versão, esse problema não ocorre, pois a função with-ne
flagsprint
não anexa a nova linha.No entanto, a correção no caso do awk é tornar condicional, como mencionado por Dope Ghoti nos comentários, é verificar o tamanho da variável temporária. A versão perl da mesma correção seria:
fonte
awk
)NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.-ne
sinalizadores não gera uma nova linha. Na verdade, é impresso, mas é uma sequência nula, sem nova linha final. No entanto, adicionei a menção do problema e a mesma correção na minha resposta. Obrigado !Vim
Não é adequado para arquivos longos, mas ainda é útil se você estivesse apenas editando um arquivo e desejasse, por exemplo, reorganizar algumas estrofes do yaml.
Primeiro grave uma macro:
E repita o número desejado de vezes:
Ou apenas por exemplo
Explicação:
fonte
@q @q @q
, é possível fazer desta maneira3@q
- repita três vezes.100@q
- repita a macro 100 vezes.Uso:
./shuffle_lines.awk input.txt
Verifique shebang
#!/usr/bin/awk -f
, porque oawk
local pode ser diferente no seu sistema.fonte