П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 3526 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 6122 раз(а).

Учебник HTML.
Просмотров 3276 раз(а).

Руководство по PHP5.
Просмотров 5499 раз(а).

Хостинг через призму DNS.
Просмотров 4151 раз(а).

Подборка текстов стандартных документов.
Просмотров 55776 раз(а).

Учебник PHP - Самоучитель
Просмотров 3093 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 5771 раз(а).

Внешние атаки...
Просмотров 3843 раз(а).

Учебник PHP.
Просмотров 2826 раз(а).

SSI в примерах.
Просмотров 37463 раз(а).



 
 
| Добавить в избранное | Сделать стартовой | Помощь





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

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

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

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.


Note

Подстанавливаемая команда выполняется в подоболочке.

Caution

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

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.


Caution

При выводе значений переменных, полученных в результате подстановки команд, командой 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".
                        #  Однако, эта команда порождает дочерний процесс,
                        #+ поэтому эта строка выполняется медленнее, чем предыдущая.

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


#  Выдержки из системного файла /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


Caution

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

Пример 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
Note

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

output=$(sed -n /"$1"/p $file)   # К примеру из
"grp.sh".
        
# Запись в переменную содержимого текстового файла.
File_contents1=$(cat $file1)
File_contents2=$(<$file2)        # Bash допускает и такую
запись.


Следует упомянуть, что в конструкции $(...) два идущих подряд обратных слэша интерпретируются несколько иначе, чем в конструкции `...`.

bash$ echo `echo \\`


bash$ echo $(echo \\)
\
        


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

  1. Пример 10-7

  2. Пример 10-26

  3. Пример 9-27

  4. Пример 12-3

  5. Пример 12-18

  6. Пример 12-15

  7. Пример 12-42

  8. Пример 10-13

  9. Пример 10-10

  10. Пример 12-27

  11. Пример 16-7

  12. Пример A-19

  13. Пример 27-2

  14. Пример 12-35

  15. Пример 12-36

  16. Пример 12-37


Назад | Вперед
Содержание (общее) | Содержание раздела



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту: