Назначение определенной строки из переменной в другую переменную

Я хотел бы взять определенную строку от переменной к другой переменной. Я пробовал это, но он не работает:

c="1.apple 2.banna 3.peach" read "Please choose fruit [1-3]:" t a=$c | awk "NR==$t" echo "You choose: $a" 

Какая у меня ошибка?

Используйте здесь перенаправление строк <<< вместе с Command Substitution $() и не забудьте поставить двойные кавычки вокруг ваших переменных :

 a=$(awk "NR==$t" <<< "$c") 

В первую очередь:

 read "Please choose fruit [1-3]:" t 

…не будет работать. Похоже, вы пытаетесь предоставить строку подсказки для встроенного read оболочки, но read интерпретирует свой первый аргумент как имя переменной, чтобы назначить значение строки, которую он читает из stdin, если только она не передается.

 read -p "Please choose fruit [1-3]:" t 

… является опцией, поддерживаемой во многих оболочках и, вероятно, ближе к тому, что вы намереваетесь делать.

Тем не менее, вы, вероятно, не должны ставить несколько значений в одноимсячном назначении, если вы ранее не остановились на том, чтобы разделить его. Когда вы выполните:

 var=' some list of things ' 

Оболочка в конечном итоге проанализирует это на что-то вроде:

 \0 some list of things \0 

… и присваивать единственное имя одному значению. Многие оболочки предлагают более предварительные формы разграничения – такие как именованные массивы, но все оболочки POSIX предоставляют по крайней мере один легко определяемый массив для каждого контекста функции – массив $@ shell. Различные реализации, предоставляющие именованные массивы, обычно имитируют поведение массива $@ shell для их названных массивов.

Поэтому вместо того, чтобы назначать все эти индивидуальные значения одной строке, как вы, вы можете сделать вместо этого:

 set apple banana peach 

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

 printf %s\\n "$1" 

… который печатает:

 apple 

Примечание. Если вы используете значения, превышающие 9, лучше всего заключить ссылку в фигурные скобки, например "${10}"

Вы можете указать количество различных строк в "$#" например:

 printf %d\\n "$#" 

… который печатает …

 3 

Вы можете указать их в списке отдельных строк:

 printf %s\\n "$@" 

… который печатает:

 apple banana peach 

… или как единая конкатенированная строка, такая как:

 printf %s\\n "$*" 

… где отдельные строки значений массива конкатенируются по первому символу, содержащемуся в переменной оболочки $IFS . Поэтому, если у вас есть значение $IFS по умолчанию <space><tab><newline> каждая строка в массиве присоединяется к следующему с помощью одного <space> между ними. Вышеприведенная команда, например, печатает:

 apple banana peach 

… но если я это сделаю:

 IFS='fruit sucks'; printf %s\\n "$*" 

… он печатает:

 applefbananafpeach 

Большинство оболочек, которые реализуют именованные расширения массивов, делают это с похожим синтаксисом, за исключением того, что различные средства обращения к массиву должны быть связаны с именем. Назначение массива обычно выглядит так:

 array=( apple banana peach ) 

…или…

 array[0]=apple array[1]=banana array[2]=peach 

По сравнению с "$1" , "$#" , "$@" , "$*" , названные массивы обычно работают как "${array[1]}" , "${#array[@]}" , "${array[@]}" и "${array[*]}" где ранее упоминавшаяся связь между "$*" и "$IFS" прежнему сохраняется для "${array[*]}" .

Как только вы правильно разделите свои ценности, ваша проблема становится намного проще:

 set apple banana peach; n=0 { for a do printf "$((n+=1)).:\t%s\n" "$a"; done printf "Please choose fruit [1-$#]: "; read t } <>/dev/tty >&0 && [ "0$((!${#t}))" -lt "0${t##*[!0-9]*}" ] && eval 'printf "You choose: %s\n" "${'"$t"}\" 

Некоторые могут издеваться над использованием eval выше, но его использование здесь не менее безопасно, чем многие могли бы сделать как "${array[$t]}" (это один из способов сделать это с помощью названных массивов), потому что "${array[$t]}" подразумевает вторую оценку $t как индекса после того, как она сначала анализируется как строка. Не проверяя его, как я делаю выше, чтобы убедиться, что он содержит хотя бы один и ничего, кроме цифры, и что он больше 0 (или любой из минимальных индексов имен именованных оболочек оболочки), любой случай может отображать непреднамеренные результаты.