Рейтинговые книги
Читем онлайн Искусство программирования на языке сценариев командной оболочки - Мендель Купер

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 53 54 55 56 57 58 59 60 61 ... 96

Упражнение 2. Просмотрите другие, более сложные сценарии из /etc/rc.d/init.d. Попробуйте разобраться в их работе. Проверьте их работу, следуя рекомендациям, приведенным выше. За дополнительной информацией вы можете обратиться к документу sysvinitfiles в каталоге /usr/share/doc/initscripts-?.??, который входит в пакет документации к "initscripts".

Глава 14. Подстановка команд

Подстановка команд -- это подстановка результатов выполнения команды[ 43 ] или даже серии команд; буквально, эта операция позволяет вызвать команду в другом окружении.

Классический пример подстановки команд -- использование обратных одиночных кавычек (`...`). Команды внутри этих кавычек представляют собой текст командной строки.

script_name=`basename $0`

echo "Имя этого файла-сценария: $script_name."

Вывод от команд может использоваться: как аргумент другой команды, для установки значения переменной и даже для генерации списка аргументов цикла for.

rm `cat filename` # здесь "filename" содержит список удаляемых файлов.

#

# S. C. предупреждает, что в данном случае может возникнуть ошибка "arg list too long".

# Такой вариант будет лучше: xargs rm -- < filename

# ( -- подходит для случая, когда "filename" начинается с символа "-" )

textfile_listing=`ls *.txt`

# Переменная содержит имена всех файлов *.txt в текущем каталоге.

echo $textfile_listing

textfile_listing2=$(ls *.txt) # Альтернативный вариант.

echo $textfile_listing2

# Результат будет тем же самым.

# Проблема записи списка файлов в строковую переменную состоит в том,

# что символы перевода строки заменяются на пробел.

#

# Как вариант решения проблемы -- записывать список файлов в массив.

# shopt -s nullglob # При несоответствии, имя файла игнорируется.

# textfile_listing=( *.txt )

#

# Спасибо S.C.

Подстанавливаемая команда может получиться разбитой на отдельные слова.

COMMAND `echo a b` # 2 аргумента: a и b

COMMAND "`echo a b`" # 1 аргумент: "a b"

COMMAND `echo` # без аргументов

COMMAND "`echo`" # один пустой аргумент

# Спасибо S.C.

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

# cd "`pwd`" # Должна выполняться всегда.

# Однако...

mkdir 'dir with trailing newline

'

cd 'dir with trailing newline

'

cd "`pwd`" # Ошибка:

# bash: cd: /tmp/dir with trailing newline: No such file or directory

cd "$PWD" # Выполняется без ошибки.

old_tty_setting=$(stty -g) # Сохранить настройки терминала.

echo "Нажмите клавишу "

stty -icanon -echo # Запретить "канонический" режим терминала.

# Также запрещает эхо-вывод.

key=$(dd bs=1 count=1 2> /dev/null) # Поймать нажатие на клавишу.

stty "$old_tty_setting" # Восстановить настройки терминала.

echo "Количество нажатых клавиш = ${#key}." # ${#variable} = количество символов в переменной $variable

#

# Нажмите любую клавишу, кроме RETURN, на экране появится "Количество нажатых клавиш = 1."

# Нажмите RETURN, и получите: "Количество нажатых клавиш = 0."

# Символ перевода строки будет "съеден" операцией подстановки команды.

Спасибо S.C.

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

dir_listing=`ls -l`

echo $dir_listing # без кавычек

# Вы наверно ожидали увидеть удобочитаемый список каталогов.

# Однако, вы получите:

# total 3 -rw-rw-r-- 1 bozo bozo 30 May 13 17:15 1.txt -rw-rw-r-- 1 bozo

# bozo 51 May 15 20:57 t2.sh -rwxr-xr-x 1 bozo bozo 217 Mar 5 21:13 wi.sh

# Символы перевода строки были заменены пробелами.

echo "$dir_listing" # в кавычках

# -rw-rw-r-- 1 bozo 30 May 13 17:15 1.txt

# -rw-rw-r-- 1 bozo 51 May 15 20:57 t2.sh

# -rwxr-xr-x 1 bozo 217 Mar 5 21:13 wi.sh

Подстановка команд позволяет даже записывать в переменные содержимое целых файлов, с помощью перенаправления или команды cat.

variable1=`<file1` # Записать в переменную "variable1" содержимое файла "file1".

variable2=`cat file2` # Записать в переменную "variable2" содержимое файла "file2".

# Замечание 1:

# Удаляются символы перевода строки.

#

# Замечание 2:

# В переменные можно записать даже управляющие символы.

# Выдержки из системного файла /etc/rc.d/rc.sysinit

#+ (Red Hat Linux)

if [ -f /fsckoptions ]; then

fsckoptions=`cat /fsckoptions`

...

fi

#

#

if [ -e "/proc/ide/${disk[$device]}/media" ] ; then

hdmedia=`cat /proc/ide/${disk[$device]}/media`

...

fi

#

#

if [ ! -n "`uname -r | grep -- "-"`" ]; then

ktag="`cat /proc/version`"

...

fi

#

#

if [ $usb = "1" ]; then

sleep 5

mouseoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=02"`

kbdoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=01"`

...

fi

Не используйте переменные для хранения содержимого текстовых файлов большого объема, без веских на то оснований. Не записывайте в переменные содержимое бинарных файлов, даже шутки ради.

Пример 14-1. Глупая выходка

#!/bin/bash

# stupid-script-tricks.sh: Люди! Будьте благоразумны!

# Из "Глупые выходки", том I.

dangerous_variable=`cat /boot/vmlinuz` # Сжатое ядро Linux.

echo "длина строки $dangerous_variable = ${#dangerous_variable}"

# длина строки $dangerous_variable = 794151

# ('wc -c /boot/vmlinuz' даст другой результат.)

# echo "$dangerous_variable"

# Даже не пробуйте раскомментарить эту строку! Это приведет к зависанию сценария.

# Автор этого документа не знает, где можно было бы использовать

#+ запись содержимого двоичных файлов в переменные.

exit 0

Обратите внимание: в данной ситуации не возникает ошибки переполнения буфера. Этот пример показывает превосходство защищенности интерпретирующих языков, таких как Bash, от ошибок программиста, над компилирующими языками программирования.

Подстановка команд, позволяет записать в переменную результаты выполнения цикла. Ключевым моментом здесь является команда echo, в теле цикла.

Пример 14-2. Запись результатов выполнения цикла в переменную

#!/bin/bash

# csubloop.sh: Запись результатов выполнения цикла в переменную

variable1=`for i in 1 2 3 4 5

do

echo -n "$i" # Здесь 'echo' -- это ключевой момент

done`

echo "variable1 = $variable1" # variable1 = 12345

i=0

variable2=`while [ "$i" -lt 10 ]

do

echo -n "$i" # Опять же, команда 'echo' просто необходима.

let "i += 1" # Увеличение на 1.

done`

echo "variable2 = $variable2" # variable2 = 0123456789

exit 0

Подстановка команд позволяет существенно расширить набор инструментальных средств, которыми располагает Bash. Суть состоит в том, чтобы написать программу или сценарий, которая выводит результаты своей работы на stdout (как это делает подавляющее большинство утилит в UNIX) и записать вывод от программы в переменную.

#include <stdio.h>

/* Программа на C "Hello, world." */

int main()

{

printf( "Hello, world." );

return (0);

}

bash$ gcc -o hello hello.c

#!/bin/bash

# hello.sh

greeting=`./hello`

echo $greeting

bash$ sh hello.sh

Hello, world.

Альтернативой обратным одиночным кавычкам, используемым для подстановки команд, можно считать такую форму записи: $(COMMAND).

output=$(sed -n /"$1"/p $file) # К примеру из "grp.sh".

# Запись в переменную содержимого текстового файла.

File_contents1=$(cat $file1)

File_contents2=$(<$file2) # Bash допускает и такую запись.

Примеры подстановки команд в сценариях:

1. Пример 10-7

2. Пример 10-26

3. Пример 9-26

4. Пример 12-2

5. Пример 12-15

6. Пример 12-12

7. Пример 12-39

8. Пример 10-13

9. Пример 10-10

10. Пример 12-24

11. Пример 16-7

12. Пример A-19

13. Пример 27-1

14. Пример 12-32

15. Пример 12-33

16. Пример 12-34

Глава 15. Арифметические подстановки

Арифметические подстановки -- это мощный инструмент, предназначенный для выполнения арифметических операций в сценариях. Перевод строки в числовое выражение производится с помощью обратных одиночных кавычек, двойных круглых скобок или предложения let.

Вариации

Арифметические подстановки в обратных одиночных кавычках (часто используются совместно с командой expr)

z=`expr $z + 3` # Команда 'expr' вычисляет значение выражения.

Арифметические подстановки в двойных круглых скобках, и предложение let

В арифметических подстановках, обратные одиночные кавычки могут быть заменены на двойные круглые скобки $((...)) или очень удобной конструкцией, с применением предложения let.

z=$(($z+3))

# $((EXPRESSION)) -- это подстановка арифметического выражения. # Не путайте с

#+ подстановкой команд.

let z=z+3

let "z += 3" # Кавычки позволяют вставляьб пробелы и специальные операторы.

# Оператор 'let' вычисляет арифметическое выражение,

#+ это не подстановка арифметического выражения.

1 ... 53 54 55 56 57 58 59 60 61 ... 96
На этой странице вы можете бесплатно читать книгу Искусство программирования на языке сценариев командной оболочки - Мендель Купер бесплатно.
Похожие на Искусство программирования на языке сценариев командной оболочки - Мендель Купер книги

Оставить комментарий