Więc jeśli mam zmienną
VAR='10 20 30 40 50 60 70 80 90 100'
i powtórz to
echo "$VAR"
10 20 30 40 50 60 70 80 90 100
Jednak w dalszej części skryptu muszę odwrócić kolejność tej zmiennej, aby wyświetlała się jako coś podobnego
echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10
Próbowałem użyć rev i dosłownie odwróciło wszystko, więc wyszło jak
echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01
Odpowiedzi:
W systemach GNU odwrotnością cat jest tac:
źródło
echo $'100 \n90 80 70 60 50 40 30 20 10'
tac -s" " <<< "$VAR "
wersji nadal wstawia wiodącą pustą linię, dodaje spację końcową i pomija znak nowej linii (jak gdybyprintf '\n%s ' "$reversed_VAR"
zamiast oczekiwanejprintf '%s\n' "$reversed_VAR"
)echo $(tac -s" " <<< $VAR)
nie ma końcowego spacji, ponieważ$(…)
usuwa końcowe znaki i spacje, jeśli IFS je ma. Moje rozwiązanie zostanie wkrótce poprawione, dzięki.W przypadku krótkiej listy i zmiennej zmienna sama powłoka jest najszybszym rozwiązaniem:
Wynik:
Uwaga: operacja rozłam w
set -- $var
bezpieczny dla dokładnego ciąg używany tutaj, ale nie będzie tak, jeśli ciąg zawiera znaki wieloznaczne (*
,?
lub[]
). Wset -f
razie potrzeby można tego uniknąć przed podziałem. Ta sama uwaga dotyczy także następujących rozwiązań (z wyjątkiem przypadków, gdy zaznaczono inaczej).Lub, jeśli chcesz ustawić inną zmienną z odwrotną listą:
Lub używając tylko parametrów pozycyjnych.
Lub używając tylko jednej zmiennej (która może być samą var):
Uwaga: Na to rozwiązanie nie ma wpływu globing ani IFS.
źródło
awk
na pomocz
perl
, dzięki uprzejmości Jak odczytać adres IP wstecz? udostępnione przez @steeldriverLub
bash
sam z siebie poprzez konwersję łańcucha na tablicęźródło
Możesz użyć funkcji bash, takich jak tablice, aby zrobić to całkowicie w trakcie:
Powinno to być najszybszym sposobem, aby to zrobić, pod warunkiem, że $ VAR nie jest bardzo duży.
źródło
VAR='+ * ?'
). Użyjset -o noglob
lub,set -f
aby to naprawić. Mówiąc bardziej ogólnie, warto wziąć pod uwagę wartość$IFS
i stan globowania podczas korzystania z operatora split + glob. Nie, że użycie tego operatora nie ma większego sensurev_a+=( ${a[$i]} )
,rev_a+=( "${a[$i]}" )
byłoby o wiele bardziej sensowne.źródło
Użyj tutaj trochę magii Python:
Sposób, w jaki to działa, jest dość prosty:
"$VAR"
paramenterem drugiego wiersza poleceńsys.argv[1]
(pierwszy parametr z-c
opcją jest zawsze tym-c
samym - samym. Zwróć uwagę na cytowanie,"$VAR"
aby zapobiec podziałowi samej zmiennej na pojedyncze słowa (co robi to przez powłokę, a nie python).split()
metody, aby podzielić ją na listę ciągów[::-1]
część jest tylko rozszerzoną składnią plastra, aby uzyskać odwrotność listy" ".join()
i drukujemyAle ci, którzy nie są wielkimi fanami Pythona, moglibyśmy
AWK
zrobić w zasadzie to samo: podzielić i wypisać tablicę na odwrót:źródło
python3 -c 'import sys;print(*reversed(sys.argv[1:]))' $VAR
$IFS
zawiera odpowiednie znaki i bez wyłączenia części glob."$VAR"
wydajnościpython3 -c 'import sys;print(*reversed(sys.argv[1].split()))' "$VAR"
zsh
:$=VAR
dzieli$VAR
się$IFS
.(Oa)
porządkuje wynikową listę w odwrotnej kolejności tablicowej.print -r --
(jak wksh
), to samo coecho -E -
(zsh
specyficzne) to niezawodne wersjeecho
: wypisuje swoje argumenty, gdy jest oddzielone spacją, zakończone znakiem nowej linii.Jeśli chcesz podzielić tylko na spację, a nie na to, co
$IFS
zawiera (spacja, tabulator, nowa linia, domyślnie nul), albo przypisz spację$IFS
, albo użyj jawnego podziału, takiego jak:Aby sortować w odwrotnej kolejności numerycznej:
POSIXly (tak też by działał
bash
):Z wbudowaną powłoką (z wyjątkiem
printf
niektórych powłok) tylko mechanizmy (lepsze dla zmiennych o krótkiej wartości):Z
awk
(lepiej dla dużych zmiennych, szczególnie zbash
, ale do granicy wielkości argumentów (lub pojedynczego argumentu)):źródło
Nieeleganckie narzędzia oprogramowania POSIX one-liner:
źródło