Den Inhalt einer Variablen wortweise umkehren

Den Inhalt einer Variablen wortweise umkehren

Wenn ich also eine Variable habe

VAR='10 20 30 40 50 60 70 80 90 100'

und es wiederholen

echo "$VAR"
10 20 30 40 50 60 70 80 90 100

Weiter unten im Skript muss ich jedoch die Reihenfolge dieser Variable umkehren, damit sie etwa so angezeigt wird:

echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10

Ich habe es mit rev versucht und es hat buchstäblich alles umgekehrt, so dass das Ergebnis folgendermaßen war:

echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01

Antwort1

Auf GNU-Systemen ist das Gegenteil von cat tac:

$ tac -s" " <<< "$VAR "            # Please note the added final space.
100 90 80 70 60 50 40 30 20 10

Antwort2

Für eine kurze Liste und in einer Variablen ist die Shell selbst die schnellste Lösung:

var="10 20 30 40 50 60 70 80 90 100"
set -- $var; unset a 
for ((i=$#;i>0;i--)); do
    printf '%s%s' "${a:+ }" "${!i}"
    a=1
done
echo

Ausgabe:

100 90 80 70 60 50 40 30 20 10 

Hinweis: Die Aufteilungsoperation set -- $varist für die hier verwendete exakte Zeichenfolge sicher, jedoch nicht, wenn die Zeichenfolge Platzhalterzeichen ( *, ?oder []) enthält. Sie kann set -fbei Bedarf mit vor der Aufteilung vermieden werden. Derselbe Hinweis gilt auch für die folgenden Lösungen (sofern nicht anders angegeben).

Oder, wenn Sie mit der umgekehrten Liste eine andere Variable festlegen möchten:

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
for i; do out="$i${out:+ }$out"; done
echo "$out"

Oder verwenden Sie nur die Positionsparameter.

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
a=''
for    i
do     set -- "$i${a:+ $@}"
       a=1
done
echo "$1"

Oder verwenden Sie nur eine Variable (die var selbst sein kann):
Hinweis: Diese Lösung wird weder durch Globing noch durch IFS beeinflusst.

var="10 20 30 40 50 60 70 80 90 100"

a=" $var"
while [[ $a ]]; do
    printf '<%s>' "${a##* }"
    var="${a% *}"
done

Antwort3

awkzur Rettung

$ var='10 20 30 40 50 60 70 80 90 100'

$ echo "$var" | awk '{for(i=NF; i>0; i--) printf i==1 ? $i"\n" : $i" "}'
100 90 80 70 60 50 40 30 20 10


mit perl, HöflichkeitWie liest man eine IP-Adresse rückwärts?geteilt von @steeldriver

$ echo "$var" | perl -lane '$,=" "; print reverse @F'
100 90 80 70 60 50 40 30 20 10


Oder mit bashsich selbst durch Konvertieren des Strings in ein Array

$ arr=($var)    
$ for ((i=${#arr[@]}-1; i>=0; i--)); do printf "${arr[i]} "; done; echo
100 90 80 70 60 50 40 30 20 10 

Antwort4

zsh:

print -r -- ${(Oa)=VAR}

$=VARteilt $VARauf $IFS. (Oa)sortiert die resultierende Liste in umgekehrter Array-Reihenfolge. print -r --(wie in ksh), dasselbe wie echo -E -( zshspezifisch) isteine zuverlässige Version vonecho: druckt seine Argumente unverändert, durch Leerzeichen getrennt und durch eine neue Zeile abgeschlossen.

Wenn Sie nur nach Leerzeichen teilen möchten und nicht nach allem, was $IFSes enthält (standardmäßig Leerzeichen, Tabulator, Zeilenumbruch, NUL), weisen Sie entweder Leerzeichen zu $IFSoder verwenden Sie eine explizite Teilung wie:

print -r -- ${(Oas: :)VAR}

So sortieren Sie in umgekehrter numerischer Reihenfolge:

$ VAR='50 10 20 90 100 30 60 40 70 80'
$ print -r -- ${(nOn)=VAR}
100 90 80 70 60 50 40 30 20 10

POSIX (würde also auch mit funktionieren bash):

Nur mit in die Shell integrierten Mechanismen (außer printfin einigen Shells) (besser für Variablen mit einem kurzen Wert):

unset -v IFS # restore IFS to its default value of spc, tab, nl
set -o noglob # disable glob
set -- $VAR # use the split+glob operator to assign the words to $1, $2...

reversed_VAR= sep=
for i do
  reversed_VAR=$i$sep$reversed_VAR
  sep=' '
done
printf '%s\n' "$reversed_VAR"

Mit awk(besser für große Variablen, insbesondere mit bash, aber bis zur Grenze der Größe der Argumente (oder eines einzelnen Arguments)):

 awk '
   BEGIN {
     n = split(ARGV[1], a);
     while (n) {printf "%s", sep a[n--]; sep = " "}
     print ""
   }' "$VAR"

verwandte Informationen