KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Мендель Купер - Искусство программирования на языке сценариев командной оболочки

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Мендель Купер, "Искусство программирования на языке сценариев командной оболочки" бесплатно, без регистрации.
Перейти на страницу:

Упражнение 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' вычисляет арифметическое выражение,

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*