Risposte:
Usando sed
per emulare tac
:
sed '1!G;h;$!d' ${inputfile}
sed
one-liner. Vedi "36. Ordine inverso delle linee (emula" tac "comando Unix)." nel famoso Sed One-Liners spiegato per una spiegazione completa di come funziona.
sort
- c'è la possibilità che userà un file temporaneo).
Con ed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
Se sei su BSD
/ OSX
(e speriamo presto su GNU
/ linux
anche come sarà POSIX ):
tail -r infile
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt
tramite awk one fodere
awk 'a=$0RS a{}END{printf a}'
but your first
perl reverse <> `è la risposta migliore / più veloce sulla pagina (per me), a 10 volte più veloce di questa awk
risposta (tutti gli awk anseres sono più o meno gli stessi, nel tempo)
awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
Come hai chiesto di farlo in bash, ecco una soluzione che non utilizza awk, sed o perl, solo una funzione bash:
reverse ()
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}
L'output di
echo 'a
b
c
d
' | reverse
è
d
c
b
a
Come previsto.
Ma attenzione che le righe sono memorizzate, una riga in ciascuna ricorsivamente chiamata istanza della funzione. Così attento con file di grandi dimensioni.
Puoi passare attraverso:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
Il awk
prefisso indica ciascuna riga con il numero di riga seguito da uno spazio. La sort
inverte l'ordine delle linee di classificare il primo campo (numero di riga) in ordine inverso, stile numerico. E le sed
strisce dai numeri di riga.
L'esempio seguente mostra questo in azione:
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'
Emette:
l
k
j
i
h
g
f
e
d
c
b
a
cat -n
si comporta in modo molto simile aawk '{print NR" "$0}'
In perl:
cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'
perl -e 'print reverse<>'
perl -pe '$\=$_.$\}{'
)
reverse<)
è veloce: buono! ma quello "veramente brutto" è estremamente lento all'aumentare del numero di righe. !! ....
-n
era superfluo lì, grazie.
sort
).
Soluzione solo BASH
leggi il file nell'array bash (una riga = un elemento dell'array) e stampa l'array nell'ordine 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=''
e read -r
per evitare che tutti i tipi di fughe e la rimozione di IFS finale possano rovinarlo. Penso che il bash mapfile ARRAY_NAME
builtin sia una soluzione migliore per la lettura negli array.
Bash, con mapfile
menzionato nei commenti a Fiximan, e in realtà una versione forse migliore:
# 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
}
Le sue prestazioni sono sostanzialmente paragonabili alla sed
soluzione e diventano più veloci al diminuire del numero di linee richieste.
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'
come mostrato qui:
echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'
Risultato:
c a f e
awk '{print NR" "$0}' | sort -nr