Обращение содержимого переменной словами

Поэтому, если у меня есть переменная

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

и повторить

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

Тем не менее, в дальнейшем по сценарию мне нужно изменить порядок этой переменной, чтобы она показывала что-то вроде

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

Я пробовал использовать rev, и это буквально перевернуло все, чтобы оно получилось как

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

8 Solutions collect form web for “Обращение содержимого переменной словами”

В системах GNU обратная сторона cat имеет значение tac:

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

Для краткого списка и в переменной сама оболочка является самым быстрым решением:

 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 

Вывод:

 100 90 80 70 60 50 40 30 20 10 

Примечание: операция split в set -- $var безопасна для точной строки, используемой здесь, но не будет такой, если строка содержит подстановочные символы ( * ? Или [] ). Его можно избежать с помощью set -f перед расколом, если это необходимо. Такая же заметка также применима к следующим решениям (за исключением случаев, когда это указано).

Или, если вы хотите установить другую переменную с обратным списком:

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

Или использовать только позиционные параметры.

 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" 

Или используя только одну переменную (которая может быть самой var):
Примечание. На это решение не влияет глобус и IFS.

 var="10 20 30 40 50 60 70 80 90 100" a=" $var" while [[ $a ]]; do printf '<%s>' "${a##* }" var="${a% *}" done 

awk на помощь

 $ 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 

с perl , любезность Как читать IP-адрес в обратном направлении? Поделился с @steeldriver

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

Или, с самим bash путем преобразования строки в массив

 $ 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 

Вы можете использовать функции bash, такие как массивы, чтобы сделать это полностью в процессе:

 #!/bin/bash VAR="10 20 30 40 50 60 70 80 90 100" a=($VAR); rev_a=() for ((i=${#a[@]}-1;i>=0;i--)); do rev_a+=( ${a[$i]} ); done; RVAR=${rev_a[*]}; 

Это должен быть самый быстрый способ сделать это при условии, что $ VAR не очень большой.

 printf "%s\n" $var | tac | paste -sd' ' 100 90 80 70 60 50 40 30 20 10 

Используйте здесь немного магии Python:

 bash-4.3$ VAR='10 20 30 40 50 60 70 80 90 100' bash-4.3$ python -c 'import sys;print " ".join(sys.argv[1].split()[::-1])' "$VAR" 100 90 80 70 60 50 40 30 20 10 

То, как это работает, довольно просто:

  • мы ссылаемся на "$VAR" качестве второго sys.argv[1] командной строки sys.argv[1] (первый параметр с параметром -c всегда есть только сам -c . Обратите внимание на цитирование вокруг "$VAR" чтобы предотвратить разделение самой переменной на отдельные слова (которые его делали оболочкой, а не питоном)
  • Затем мы используем .split() , чтобы разбить его на список строк
  • [::-1] часть – это просто расширенный синтаксис фрагмента, чтобы получить обратный список
  • наконец, мы объединяем все вместе в одну строку с помощью " ".join() и распечатываем

Но те, кто не являются большими поклонниками Python, мы могли бы использовать AWK чтобы сделать практически то же самое: split и print array в обратном порядке:

  echo "$VAR" | awk '{split($0,a);x=length(a);while(x>-1){printf "%s ",a[x];x--};print ""}' 100 90 80 70 60 50 40 30 20 10 

zsh :

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

$=VAR разделяет $VAR на $IFS . (Oa) заказывает результирующий список в порядке обратного массива. print -r -- (как в ksh ), то же самое, что и echo -E - ( zsh specific) – надежные версии echo : печатает свои аргументы как-разделенные пробелом, завершенные новой строкой.

Если вы хотите разделить только на пробел, а не на то, что содержит $IFS (пробел, табуляция, новая строка, нуль по умолчанию), либо присваивать пространство $IFS , либо использовать явное расщепление:

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

Для сортировки в обратном порядке:

 $ 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 

POSIXly (так же будет работать и с bash ):

Только с встроенными оболочками (за исключением printf в некоторых оболочках) (лучше для переменных с коротким значением):

 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" 

С awk (лучше для больших переменных, особенно с bash , но до предела размера аргументов (или одного аргумента):

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

Непрозрачные программные средства POSIX однострочный:

 echo `echo $VAR | tr ' ' '\n' | sort -nr` 
  • Команда, с которой был запущен процесс
  • Сценарий Wrapper для отображения файлов с исходными кодами / исполняемых файлов
  • Заказ исполняемых файлов стартовал в bash
  • Форматирование вывода сценария оболочки
  • код выхода команды ** перед ** последним?
  • Запуск сценария bash как root предотвращает асинхронное выполнение?
  • Переменная Shell в теге <a href>
  • Как Git меняет приглашение оболочки в Cygwin Terminal Aptana Studio?
  • Сценарий оболочки с циклом for и "array"
  • Как войти в папку foo- * без фактического использования подстановочных или оболочечных расширений?
  • Установка пакетов и инструментов в локальном нестандартном каталоге
  • Linux и Unix - лучшая ОС в мире.