Respostas:
Usando sed
para emular tac
:
sed '1!G;h;$!d' ${inputfile}
sed
. Consulte "36. Ordem inversa de linhas (emule o comando Unix" tac ")". em Famous Sed One-Liners Explained para uma explicação completa de como funciona.
sort
- há uma chance de que ele use um arquivo temporário).
Com ed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
Se você estiver em BSD
/ OSX
(e espero que em breveGNU
/ linux
também como será o POSIX ):
tail -r infile
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt
via awk one liners
awk 'a=$0RS a{}END{printf a}'
but your first
Perl reverter <> `que a melhor resposta / mais rápido na página (para mim), a 10 vezes mais rápido do que este awk
resposta (todos os anseres awk são sobre o mesmo, o tempo-wise)
awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
Como você pediu no bash, eis uma solução que não utiliza awk, sed ou perl, apenas uma função do bash:
reverse ()
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}
A saída de
echo 'a
b
c
d
' | reverse
é
d
c
b
a
Como esperado.
Mas tenha cuidado que as linhas são armazenadas na memória, uma linha em cada recursivamente chamada instância da função. Tome cuidado com arquivos grandes.
Você pode canalizá-lo através de:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
O awk
prefixo de cada linha com o número da linha seguido por um espaço. A sort
inverte a ordem das linhas pela triagem no primeiro campo (número de linha) em ordem inversa, estilo numérico. E as sed
tiras dos números de linha.
O exemplo a seguir mostra isso em ação:
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'
Emite:
l
k
j
i
h
g
f
e
d
c
b
a
cat -n
age comoawk '{print NR" "$0}'
Em perl:
cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'
perl -e 'print reverse<>'
perl -pe '$\=$_.$\}{'
)
reverse<)
é rápido: bom! mas o "muito feio" é extremamente lento como o número de linhas aumenta !! .....
-n
era supérfluo lá, obrigado.
sort
).
Solução somente BASH
leia o arquivo no array bash (uma linha = um elemento do array) e imprima o array na ordem inversa:
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=''
e read -r
para impedir que todos os tipos de fugas e remoção posterior do IFS estragem. Eu acho que o bash mapfile ARRAY_NAME
builtin é uma solução melhor para a leitura de matrizes.
Bash, mapfile
mencionado nos comentários para fiximan, e na verdade uma versão possivelmente melhor:
# 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
}
Seu desempenho é basicamente comparável à sed
solução e fica mais rápido à medida que o número de linhas solicitadas diminui.
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 mostrado aqui:
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