web-dev-qa-db-fra.com

Comment puis-je imprimer des lignes de fichier à l'envers (sans utiliser "TAC")?

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?

26
Ionut Ungureanu

En utilisant sed pour émuler tac:

sed '1!G;h;$!d' ${inputfile}
35
Johnsyweb

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
8
don_crissti

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
4
user14408

À Perl:

cat <somefile> | Perl -e 'while(<>) { Push @a, $_; } foreach (reverse(@a)) { print; }'
1
Frederik Deweerdt

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
0
Fiximan
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'

0
Bipul kumar

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.

0
Arthur2e5
  • Numérotez les lignes avec NL
  • trier dans l'ordre inverse par numéro
  • supprimer les chiffres avec SED

comme indiqué ici:

echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'

Résultat:

c
a
f
e
0
user unknown