Получение значений из переменных - скрипт bash

Прокомментируйте следующую строку в файле /etc/init/control-alt-delete.conf

#exec shutdown -r теперь «Control-Alt-Delete нажато»

[d2 ] См. Больше на: http://www.tecgeeks.com/ubuntu/how-to-disable-ctrl-alt-delete-in-ubuntu/
1
задан 25 January 2014 в 01:57

3 ответа

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

Вот как вы можете сделать это с помощью eval для доступа к переменным, следуя тесному способу, который дал OP как его код:

INPUT1=/tmp/dir1
INPUT2=/tmp/dir2
INPUT3=/tmp/dir3

for i in {1..3} ; do
    eval "echo \$INPUT$i"
done

Выход:

/tmp/dir1
/tmp/dir2
/tmp/dir3
3
ответ дан 24 May 2018 в 18:41

Лучший способ - определить переменную INPUT как массив:

#!/bin/bash

INPUT[1]=/tmp/dir1
INPUT[2]=/tmp/dir2
INPUT[3]=/tmp/dir3

for i in "${INPUT[@]}"
do 
echo $i     #or $INPUT[$i]
done

См. также: http://www.cyberciti.biz/faq/bash-for-loop-array/

0
ответ дан 24 May 2018 в 18:41
  • 1
    Это не работает. " для i в " $ {INPUT [@]} "& quot ;. Я получаю следующую ошибку: синтаксическая ошибка: ожидаемый операнд (токен ошибки есть .. – Ubuntuser 4 September 2013 в 12:02
  • 2
    @Ubuntuser Используете ли вы оболочку bash, указав свой вопрос? Или как вы запускаете скрипт? – Radu Rădeanu 4 September 2013 в 12:07
  • 3
    Да, его bash в Ubuntu 13.04. for i in {0,1,2}; работает для меня – Ubuntuser 4 September 2013 в 12:10
  • 4
    @Ubuntuser Как запустить сценарий? – Radu Rădeanu 4 September 2013 в 12:12
  • 5
    ./script-name.sh - это то, что я использую. – Ubuntuser 4 September 2013 в 12:36

bash фактически поддерживает что-то довольно близкое к тому, что вы в первый раз пытались.

INPUT1=/tmp/dir1
INPUT2=/tmp/dir2
INPUT3=/tmp/dir3

for s in INPUT{1..3}; do
    echo ${!s}
done

Это работает, потому что:

INPUT{1..3} расширяется до INPUT1 INPUT2 INPUT3. (Это эквивалентно INPUT{1,2,3}.) Там, где $s является расширением s, ${!s} является расширением разложения s. Например, в первой итерации цикла, если появился $s, он будет расширен до INPUT1. Если появился $INPUT1, он будет расширен до /tmp/dir1. Таким образом, ${!s} расширяется до /tmp/dir1. Такое расширение параметра называется косвенным расширением. В этой ситуации и многим подобным, встроенный синтаксис ! достигает этого более компактно и элегантно, чем eval. Для получения дополнительной информации см. Можно ли построить имена переменных из других переменных в bash? на переполнение стека.

Некоторые предостережения (которые также применимы к некоторым другим ответам, которые были опубликованы):

INPUT{1..3} расширяется до INPUT1 INPUT2 INPUT3. (Это эквивалентно INPUT{1,2,3}.)

INPUT{1..3} расширяется до INPUT1 INPUT2 INPUT3. (Это эквивалентно INPUT{1,2,3}.)

В настоящее время это -, а затем еще один e, E или n. Но вы, вероятно, должны рассматривать что-либо, начиная с -, как опасное, если будущие версии bash добавляют новые параметры.

Если какой-либо из INPUTn может принять значение, которое echo будет интерпретировать как вариант вместо текста для печати, замените echo на printf '%s\n' .3

INPUT{1..3} расширяется до INPUT1 INPUT2 INPUT3. (Это эквивалентно INPUT{1,2,3}.)

В настоящее время это -, а затем еще один e, E или n. Но вы, вероятно, должны рассматривать что-либо, начиная с -, как опасное, если будущие версии bash добавляют новые параметры.
Где $s - расширение s, ${!s} - расширение разложения of s. Например, в первой итерации цикла, если появился $s, он будет расширен до INPUT1. Если появился $INPUT1, он будет расширен до /tmp/dir1. Таким образом, ${!s} расширяется до /tmp/dir1. Такое расширение параметра называется косвенным расширением. В этой ситуации и многим подобным, встроенный синтаксис ! достигает этого более компактно и элегантно, чем eval. Для получения дополнительной информации см. Можно ли построить имена переменных из других переменных в bash? (! d6)

Хотя в терминах синтаксиса косвенное расширение, представленное выше, почти так же просто, как это делается с массивом, вы все равно можете использовать массив, потому что:

Возможно, вы намеревались /tmp/dir1, /tmp/dir2 и /tmp/dir3 как непрозрачные примеры, которые могут быть заменены чем-либо.

input=(/tmp/dir{1..3})

Но если вы действительно хотите создать массив эти конкретные значения, я рекомендую:

for s in /tmp/dir{1..3}; do
    echo $s
done

Точно так же, если ваша цель состоит в том, чтобы просто пропустить /tmp/dir1, /tmp/dir2 и /tmp/dir3 и выполнить какое-то действие с каждым, тогда вы все равно захотите использовать массив :

for s in '/tmp/dir '{1..3}' with  spaces'; do
    echo "$s"
done

Если значения s будут содержать пробелы или специальные символы (см. выше), процитируйте их, но оставьте {...} диапазон без кавычек, отдельно цитируя текст слева и справа от него - он не будет расширяться при цитировании даже в двойных кавычках.

/tmp/dir 1 with  spaces
/tmp/dir 2 with  spaces
/tmp/dir 3 with  spaces

Что печатает:

printf '%s\n' /tmp/dir{1..3}

И если ваша цель - просто напечатать /tmp/dir1, /tmp/dir2 и /tmp/dir3, каждый на своей собственной линии, и 3 достаточно:

3 : оболочка разбивает текст на слова в пробеле или, если определена переменная IFS, в поле которые он задает. Но вам обычно не нужно беспокоиться о IFS, если вы не установили его сами.

2: echo hello world на самом деле работает: он печатает hello world, как echo 'hello world'. Это связано с тем, что echo печатает одно пространство между каждым эхо-аргументом. Однако echo hello world не эквивалентен echo 'hello world': первый по-прежнему печатает hello world, а последний печатает hello world.

0
ответ дан 24 May 2018 в 18:41

Другие вопросы по тегам:

Похожие вопросы: