Respuestas:
Usando sed
para emular tac
:
sed '1!G;h;$!d' ${inputfile}
sed
one-liner. Consulte "36. Orden inverso de líneas (emular" tac "comando Unix)". en el famoso Sed One-Liners explicado para una explicación completa de cómo funciona.
sort
, existe la posibilidad de que use un archivo temporal).
Con ed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
Si está en BSD
/ OSX
(y con suerte pronto en GNU
/ linux
también, ya que será POSIX ):
tail -r infile
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt
a través de awk one liners
awk 'a=$0RS a{}END{printf a}'
but your first
perl reverse <> `es la respuesta mejor / más rápida en la página (para mí), 10 veces más rápido que esta awk
respuesta (todos los awk anseres son casi iguales, en cuanto al tiempo)
awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
Como pediste hacerlo en bash, aquí hay una solución que no utiliza awk, sed o perl, solo una función bash:
reverse ()
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}
La salida de
echo 'a
b
c
d
' | reverse
es
d
c
b
a
Como se esperaba.
Pero tenga en cuenta que las líneas se almacenan en la memoria, una línea en cada instancia recursivamente llamada instancia de la función. Tan cuidadoso con los archivos grandes.
Puedes canalizarlo a través de:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
Los awk
prefijos de cada línea con el número de línea seguido de un espacio. El sort
invierte el orden de las líneas de clasificación en el primer campo (número de línea) en orden inverso, estilo numérico. Y las sed
tiras de los números de línea.
El siguiente ejemplo muestra esto en acción:
pax$ echo 'a
b
c
d
e
f
g
h
i
j
k
l' | awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
Produce:
l
k
j
i
h
g
f
e
d
c
b
a
cat -n
actúa comoawk '{print NR" "$0}'
En perl:
cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'
perl -e 'print reverse<>'
perl -pe '$\=$_.$\}{'
)
reverse<)
es rápido: ¡bien! pero el "realmente feo" es extremadamente lento a medida que aumenta el número de líneas. !! ....
-n
fue superfluo allí, gracias.
sort
).
Solución solo BASH
lea el archivo en la matriz bash (una línea = un elemento de la matriz) e imprima la matriz en orden inverso:
i=0
while read line[$i] ; do
i=$(($i+1))
done < FILE
for (( i=${#line[@]}-1 ; i>=0 ; i-- )) ; do
echo ${line[$i]}
done
while..read
.
IFS=''
y read -r
para evitar que todo tipo de fugas y la eliminación de IFS final lo arruinen. Sin mapfile ARRAY_NAME
embargo, creo que bash builtin es una mejor solución para leer en matrices.
Bash, con los mapfile
comentarios mencionados en Fiximan, y en realidad una versión posiblemente mejor:
# last [LINES=50]
_last_flush(){ BUF=("${BUF[@]:$(($1-LINES)):$1}"); } # flush the lines, can be slow.
last(){
local LINES="${1:-10}" BUF
((LINES)) || return 2
mapfile -C _last_flush -c $(( (LINES<5000) ? 5000 : LINES+5 )) BUF
BUF=("${BUF[@]}") # Make sure the array subscripts make sence, can be slow.
((LINES="${#BUF[@]}" > LINES ? LINES : "${#BUF[@]}"))
for ((i="${#BUF[@]}"; i>"${#BUF[@]}"-LINES; i--)); do echo -n "${BUF[i]}"; done
}
Su rendimiento es básicamente comparable a la sed
solución, y se acelera a medida que disminuye el número de líneas solicitadas.
Simple do this with your file to sort the data in reverse order, and it should be unique.
sed -n '1h; 1d; G; h; $ p'
como se muestra aquí:
echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'
Resultado:
c a f e
awk '{print NR" "$0}' | sort -nr