Je souhaite imprimer des lignes d'un fichier à l'envers sans utiliser tac
commande. Y a-t-il une autre solution pour faire une telle chose avec Bash?
En utilisant sed
pour émuler tac
:
sed '1!G;h;$!d' ${inputfile}
Avec ed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
Si vous êtes sur BSD
/OSX
(et j'espère bientôt sur GNU
/linux
aussi comme Il sera POSIX ):
tail -r infile
Vous pouvez le faire pipi:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
Le awk
préfixe chaque ligne avec le numéro de ligne suivi d'un espace. Le sort
inverse l'ordre des lignes en triant sur le premier champ (numéro de ligne) dans l'ordre inverse, style numérique. Et le sed
bandes des numéros de ligne.
L'exemple suivant montre cela en action:
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'
Il génère:
l
k
j
i
h
g
f
e
d
c
b
a
À Perl:
cat <somefile> | Perl -e 'while(<>) { Push @a, $_; } foreach (reverse(@a)) { print; }'
Solution bash-seule
lire le fichier dans une matrice Bash (une ligne = un élément de tableau) et imprimer une matrice dans l'ordre inverse:
i=0
while read line[$i] ; do
i=$(($i+1))
done < FILE
for (( i=${#line[@]}-1 ; i>=0 ; i-- )) ; do
echo ${line[$i]}
done
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'
Bash, avec mapfile
mentionné dans les commentaires à Fiximan, et en fait une version éventuellement meilleure:
# 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
}
Sa performance est fondamentalement comparable à la solution sed
et devient plus rapide car le nombre de lignes demandées diminue.
comme indiqué ici:
echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'
Résultat:
c a f e