Tengo un archivo 'prueba' en Linux con los siguientes datos.
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
Necesito cortar la última línea de este archivo y ponerlo en la segunda posición. Debe verse a continuación.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Tengo un archivo 'prueba' en Linux con los siguientes datos.
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
Necesito cortar la última línea de este archivo y ponerlo en la segunda posición. Debe verse a continuación.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Respuestas:
Este problema podría ser más fácil de hacer ed
, ya que es básicamente un editor de texto programable, en lugar de un procesador de flujo. Utilizando ed
, no tiene que guardar todas las líneas del archivo en una matriz, por ejemplo, ya que ya lo está haciendo por usted.
# 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
... eso H
envejecerá cada línea que !
no sea la primera, y la primera que se p
traza. En la $
última línea, x
cambia los espacios de espera y de patrón antes de que haga lo H
anterior, que agrega las líneas guardadas a la última línea, y luego d
elige de la salida todas las líneas que !
no son las $
últimas.
En la $
última línea, x
cambia de nuevo los espacios, s///
sustituye el primer \n
carácter de línea de hilo, que se encarga del agregado adicional en la línea 2, y luego imprime automáticamente el lote.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
cat <<\IN >infile
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN
... solo para guardar su ejemplo en un archivo real ...
sed '1p;$!d;r infile' <infile | sed '3d;$d'
Que redirige <infile
a los primeros sed
s' stdin
, que sólo p
Rints la primera línea antes de d
eleting de salida de todas las líneas que son !
no la $
última. La última línea es autoprinted, pero también es la única línea en la que se ejecuta la orden final - que es a r
ead a cabo la totalidad infile
de nuevo a stdout
. Todo eso pasa por la |
tubería al segundo, sed
que luego solo tiene que d
elegir de su salida sus líneas de entrada tercera y final para completar la reorganización.
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
awk
- nunca lo he intentado. tal vez algún día ...
Un enfoque ingenuo usando 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
Usted almacena cada línea en la a
matriz, luego imprime la matriz en el orden que desee (primera línea, última ( NR
) y del 2 al penúltimo.
Usando una combinación de cabeza / cola y sed:
~$ head -1 f;tail -1 f;sed '1d;$d' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Imprima la primera línea, la última, y con sed elimine la primera y la última.
Solo con sed, solo he podido encontrar este comando. Estoy seguro de que hay mejores formas:
~$ sed '${p;x;s/^\n//;p};2,${H;d}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Si es la primera línea, imprímala (por defecto).
Desde la segunda línea, colóquelo en el búfer de retención ( H
) y elimine el espacio del patrón ( d
). Y si es la última línea, imprímala ( p
), luego obtenga el búfer de retención ( x
), elimine la línea vacía ( s/^\n//
) e imprímala ( p
).
sed
parte sería algo así head -n -1 f | tail -n +2
.
-1
sintaxis para head
no es portátil.
Con perl:
perl -e 'my @lines = <>; print for @lines[0, $#lines, 1..$#lines-1]' file
Con awk:
$ awk '
{lines[NR]=$0}
END{
print lines[1], lines[NR];
for (i=2; i<NR; i++) {print lines[i]}
}
' OFS=$'\n' file
SALIDA
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
awk
soluciones, ¿eres un gransed
admirador o quizás escribistesed
? ;-)