Eu tenho um arquivo 'teste' no linux com os dados abaixo.
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
Preciso cortar a última linha deste arquivo e colocá-lo na segunda posição. Deve parecer como abaixo.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Eu tenho um arquivo 'teste' no linux com os dados abaixo.
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
Preciso cortar a última linha deste arquivo e colocá-lo na segunda posição. Deve parecer como abaixo.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Respostas:
Na verdade, esse problema pode ser mais fácil ed
, pois é basicamente um editor de texto com script, em vez de um processador de fluxo. Usando ed
, você não precisa salvar todas as linhas do arquivo em uma matriz, por exemplo, pois já está fazendo isso por você.
# Create test file
~> printf "%s\n" aaaaaa bbbbbb cccccc dddddd eeeeee >test.txt
~> cat test.txt
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
# Use ed to open the file, move the last line after the first, save, and quit
~> printf "%s\n" '$m1' wq | ed test.txt
35
35
~> cat test.txt
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
sed '$x;1!H;1p;$!d;x;s/\n//
' <<\IN
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN
... que H
envelhecerá todas as linhas que !
não são a primeira e a primeira que p
é Na $
última linha, ele x
altera os espaços de espera e de padrão antes da H
antiga - que obtém as linhas salvas anexadas à última linha - e d
elimina da saída todas as linhas que !
não são as $
últimas.
Na $
última linha, ele x
muda de espaço novamente, s///
substituindo o primeiro \n
caractere de linha de linha - que cuida do extra adicionado na linha 2 - e imprime automaticamente o lote.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
cat <<\IN >infile
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN
... apenas para salvar seu exemplo em um arquivo real ...
sed '1p;$!d;r infile' <infile | sed '3d;$d'
Que redireciona <infile
para os primeiros sed
s' stdin
, que só p
rints a primeira linha antes d
eleting de saída de todas as linhas que são !
e não o $
último. A última linha é autoprinted, mas também é a única linha em que o comando final é executada - que é a r
ead a inteira infile
novamente para stdout
. Tudo isso passa pelo |
tubo para o segundo, sed
que só precisa d
eliminar de sua saída suas terceira e última linhas de entrada para concluir a reorganização.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
awk
- eu nunca tentei. talvez um dia ...
Um método ingênuo usando o awk:
~$ awk '{a[NR]=$0}END{print a[1];print a[NR];for(i=2;i<NR;i++){print a[i]}}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Você armazena todas as linhas da a
matriz e imprime a matriz na ordem que desejar (1ª linha, última ( NR
) e de 2 a penúltima.
Usando uma combinação de cabeça / cauda e sed:
~$ head -1 f;tail -1 f;sed '1d;$d' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Imprima a primeira linha, a última e, com sed, exclua a primeira e a última.
Somente com o sed, só consegui encontrar este comando. Estou certo de que existem maneiras melhores:
~$ sed '${p;x;s/^\n//;p};2,${H;d}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Se for a primeira linha, imprima-a (padrão).
Na segunda linha, coloque-o no buffer de espera ( H
) e exclua-o do espaço do padrão ( d
). E se for a última linha, imprima-a ( p
), obtenha o buffer de espera ( x
), exclua a linha vazia ( s/^\n//
) e imprima-a ( p
).
sed
peça seria algo parecido head -n -1 f | tail -n +2
.
-1
sintaxe, pois head
não é portátil.
Com perl:
perl -e 'my @lines = <>; print for @lines[0, $#lines, 1..$#lines-1]' file
Com awk:
$ awk '
{lines[NR]=$0}
END{
print lines[1], lines[NR];
for (i=2; i<NR; i++) {print lines[i]}
}
' OFS=$'\n' file
RESULTADO
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
awk
soluções, você é um grandesed
fã ou talvez tenha escritosed
? ;-)