#!/bin/sh
х=0
while [ "$х" -ne 10 ]; do
echo $х
х=$(($x+1))
done
exit 0
Обратите внимание на тонкое отличие приведенной подстановки от команды х=$(...)
. Двойные скобки применяются для подстановки значений в арифметические выражения. Вариант с одиночными скобками, показанный ранее, используется для выполнения команд и перехвата их вывода.
Вы уже видели простейший вариант присваивания параметра и подстановки значения параметра:
foo=fredecho $foo
Проблема возникает, когда вы хотите вставить дополнительные символы в конец значения переменной. Предположим, что вы хотите написать короткий сценарий обработки файлов 1_tmp и 2_tmp. Вы могли бы написать следующие строки:
#!/bin/sh
for i in 1 2 do
my_secret_process $i_tmp
done
Но в каждом проходе цикла вы получите следующее сообщение:
my_secret_process: too few arguments
В чем ошибка?
Проблема заключается в том, что командная оболочка попыталась подставить значение переменной $i_tmp
, которая не существует. Оболочка не считает это ошибкой; она просто не делает никакой подстановки, поэтому в сценарий my_secret_process не передаются никакие параметры. Для обеспечения подстановки в переменную части ее значения $i
необходимо i
заключить в фигурные скобки следующим образом:
#!/bin/sh
for i in 1 2 do
my_secret_process ${i}_tmp
done
В каждом проходе цикла вместо ${i}
подставляется значение i
и получаются реальные имена файлов. Вы подставляете значение параметра в строку.
В командной оболочке можно выполнять разнообразные виды подстановок. Часто они помогают найти красивое решение задач, требующих обработки многих параметров. Самые распространенные виды подстановок значений параметров приведены в табл. 2.18.
Таблица 2.18
Шаблон подстановки параметра | Описание |
---|---|
${парам:-значение по умолчанию}
|
Если упарам нет значения, ему присваивается значение по умолчанию |
${#парам}
|
Задается длинапарам |
${парам%строка}
|
От конца значенияпарам отбрасывается наименьшая порция, совпадающая сострокой , и возвращается остальная часть значения |
${парам%%строка}
|
От конца значенияпарам отбрасывается наибольшая порция, совпадающая сострокой , и возвращается остальная часть значения |
${парам#строка}
|
От начала значенияпарам отбрасывается наименьшая порция, совпадающая сострокой , и возвращается остальная часть значения |
${парам##строка}
|
От начала значенияпарам отбрасывается наибольшая порция, совпадающая сострокой , и возвращается остальная часть значения |
Эти подстановки очень полезны при работе со строками. Последние четыре варианта, удаляющие части строк, особенно пригодятся при обработке имен файлов и путей к ним, как показано в упражнении 2.18.
В приведенном далее сценарии показано применение шаблонов при подстановках значений параметров.
#!/bin/sh
unset foo
echo ${foo:-bar}
foo=fud
echo ${foo:-bar}
foo=/usr/bin/X11/startx
echo ${foo#*/}
echo ${foo##*/}
bar=/usr/local/etc/local/networks
echo ${bar%local*}
echo ${bar%%local*}
exit 0
У этого сценария следующий вывод:
bar
fud
usr/bin/X11/startx
startx
/usr/local/etc/usr
Как это работает
Первая подстановка ${foo:-bar}
дает значение bar
, поскольку у foo
нет значения в момент выполнения команды. Переменная foo
остается неизменной, т.е. она остается незаданной.
Подстановка ${foo:=bar}
установила бы значение переменной $foo
. Этот строковый шаблон устанавливает, что переменная foo
существует и не равна null
. Если значение переменной не равно null
, оператор возвращает ее значение, в противном случае вместо этого переменной foo
присваивается значение bar
.
Подстановка ${foo:?bar}
выведет на экран foo: bar
и аварийно завершит команду, если переменной foo
не существует или ее значение не определено. И наконец, ${foo:+bar}
вернет bar
, если foo
существует и не равна null
. Какое разнообразие вариантов!
Шаблон {foo#*/}
задает поиск и удаление только левого символа /
(символ *
соответствует любой строке, в том числе и пустой). Шаблон {foo##*/}
задает поиск максимальной подстроки, совпадающей с ним, и, таким образом, удаляет самый правый символ / и все предшествующие ему символы.