echo
Отображает сообщения или включает или отключает функцию эхо-команды. При использовании без параметров эхо отображает текущий параметр эхо.
Синтаксис
echo [] echo [on | off]
Параметры
| Параметр | Описание |
|---|---|
| [on | off] | Включает или отключает функцию эхо команды. По умолчанию выполняется эхо команды. |
| Указывает текст, отображаемый на экране. | |
| /? | Отображение справки в командной строке. |
Замечания
- Команда echo удобнее при отключении эха . Чтобы отобразить сообщение с несколькими строками без отображения каких-либо команд, можно включить несколько echo команд после команды отключения в пакетную программу.
- После отключения эха командная строка не отображается в окне командной строки. Чтобы отобразить командную строку, введите эхо.
- Если используется в пакетном файле, эхо-отключаетсяи не влияет на настройку в командной строке.
- Если во время использования эхо есть пустая переменная в пакетном файле, отображается сообщение «ECHO отключено». Чтобы предотвратить просмотр этого сообщения и создать пустую строку, поместите двоеточие ( : ) между эхом и переменной. Например: echo:%var% .
- Чтобы предотвратить повторение определенной команды в пакетном файле, вставьте перед командой вход ( @ ). Чтобы предотвратить повторение всех команд в пакетном файле, включите команду echo off в начале файла.
- Чтобы отобразить восклицательный знак ( ! ) в пакетных скриптах, заключите слово или фразу в двойные кавычки, за которым следует курсор перед восклицательным знаком ( «Hello World^!» ). Кроме того, двойной курсор ( ^^ ) можно использовать без необходимости в двойных кавычках ( Hello World^^! ).
- Чтобы отобразить канал ( | ), амперсанд () или символ < перенаправления ( & или >) при использовании эхо, используйте курсор ( ^ ) непосредственно перед этим символом. Например, ^| , ^& , ^> или ^ < . Чтобы отобразить курсор, введите два элемента в последовательности ( ^^ ).
Примеры
Чтобы отобразить текущий параметр эхо , введите:
echo
Чтобы эхо пустой строки на экране, введите следующее:
echo.
Не включайте пространство до периода. В противном случае период отображается вместо пустой строки.
Чтобы предотвратить эхо-команды в командной строке, введите следующее:
echo off
При отключении эха командная строка не отображается в окне командной строки. Чтобы снова отобразить командную строку, введите эхо.
Чтобы предотвратить отображение всех команд в пакетном файле (включая команду отключения ) на экране, в первой строке типа пакетного файла:
@echo off
Вы можете использовать команду echo в рамках инструкции if . Например, чтобы найти текущий каталог для любого файла с расширением RPT-файла, а также отправить сообщение, если такой файл найден, введите:
if exist *.rpt echo The report has arrived.
Следующий пакетный файл ищет текущий каталог для файлов с расширением имени файла TXT и отображает сообщение, указывающее результаты поиска:
@echo off if not exist *.txt ( echo This directory contains no text files. ) else ( echo This directory contains the following text files: echo. dir /b *.txt )
Если при выполнении пакетного файла не найдены файлы TXT, отобразится следующее сообщение:
This directory contains no text files.
Если файлы .txt найдены, когда пакетный файл запускается, отображаются следующие выходные данные (например, предполагается, что файлы File1.txt, File2.txt и File3.txt существуют):
This directory contains the following text files: File1.txt File2.txt File3.txt
Дополнительные ссылки
Команда ECHO — вывод текста на экран консоли
Команда ECHO наверно является одной из самых простых и самых используемых команд. Применяется для вывода текстовых сообщений на стандартный вывод и для переключения режима отображения команд на экране.
Формат командной строки:
ECHO [ON | OFF] — включить / выключить режим отображения вводимых команд на экране.
ECHO [сообщение] отобразить текст сообщения на экране.
ECHO — при вводе команды без параметров, отображается текущий режим отображения команд:
Режим вывода команд на экран (ECHO) включен.
Для вывода пустой строки, используется команда ECHO с точкой:
echo Hello World. — вывод сообщения Hello World. на экран.
echo %USERNAME% — вывод на экран значения переменной окружения USERNAME (имени текущего пользователя)
Наиболее распространено использование команды echo в командных файлах. Практически любой командный файл начинается командой
@echo off — отключить режим вывода команд на экран. Символ @ перед командой echo используется для того, чтобы на экран не выводился и текст самой команды.
Очень часто команда echo используется для записи сообщений в текстовый файл с использованием перенаправлением вывода:
echo Начало работы — %DATE% в %TIME% >logfile.txt
Echo ERORLEVEL=%ERRORLEVEL% >> logfile.txt
Echo Конец работы, %DATE% в %TIME% >>logfile.txt
В текстовый файл logfile.txt записывается дата и время начала работы командного файла, некоторые результаты и время завершения.
Нередко, команда echo используется для создания нового файла:
echo 1 >newfile.cmd — вывести символ «1» в файл newfile.cmd . Если такого файла не существует, он будет создан, если существует, то будет перезаписан.
Значения параметров командной строки, переменных и их подстановочных значений, также нередко отображаются с помощью команды echo . Пример командного файла, выводящего на экран информацию о себе:
@echo off
ECHO ОБРАБАТЫВАЕТСЯ ФАЙЛ — %0
ECHO Дата/время создания/изменения командного файла — %~t0
ECHO Путь командного файла — «%~f0»
ECHO Диск командного файла — %~d0
ECHO Каталог командного файла — «%~p0»
ECHO Имя командного файла — %~n0
ECHO Расширение командного файла — %~x0
ECHO Короткое имя и расширение — %~s0
ECHO Атрибуты командного файла — %~a0
ECHO Размер командного файла — %~z0
При выводе служебных символов, интерпретируемых командным процессором нужно использовать символ ^ . Например, вместо значения переменной ERRORLEVEL, нужно вывести текст “%ERRORLEVEL%”
ECHO ^%ERRORLEVEL^% = %ERRORLEVEL%
Особенностью команды ECHO является добавление служебных символов возврата каретки и перевода строки 0x0D и 0x0A (Carriage Return и Line Feed) в конец выводимого текста. Командный файл следующего содержания выводит текст из 3-х строк:
Если же требуется вывести весь текст в одну строку, обычно используют эмуляцию команды ECHO командой SET с параметром /P, используемой для организации диалога с пользователем, когда выводится сообщение, на которое требуется ответ. Выводимое сообщение можно использовать таким же образом, как и в команде ECHO, а вместо ответа можно использовать ввод с фиктивного устройства nul :
При выполнении такого командного файла сообщение на экране будет представлено одной строкой:
Для подачи звуковых сигналов можно использовать вывод служебного символа с кодом 07 (BELL). Достаточно просто включить его в поток выходных данных, что зависит от возможностей редактора, который используется для написания командного файла. Можно использовать и стандартные возможности командной строки, добавив комбинацию CTRL+G :
echo echo ^G > beepcmd.bat
После выполнения данной команды будет создан командный файл beepcmd.bat , который выводит командой ECHO служебный символ 07, т.е. включает писк динамика. При необходимости его можно вызывать в других командных файлах с помощью команды CALL.
Echo что за команда
Выводит на экран или скрывает текст командного файла при его выполнении. Показывает также, включено или выключено средство эхоотображения. При запуске командного файла MS-DOS обычно отображает выполняемые команды на экране. Этот режим можно выключить или включить.
ECHO [ON OFF]
Чтобы использовать команду для вывода сообщения, запишите:
echo [сообщение]
Параметр ON OFF определяет, нужно ли включить или выключить эхоотображение. Чтобы вывести на экран текущую установку, задайте команду ECHO без параметра. «Сообщение» задает текст выводимого на экран сообщения.
О приостановке выполнения командного файла рассказывается в описании команды PAUSE.
Команду ECHO с параметром сообщения полезно использовать при выключенном эхоотображении. Для вывода длинного сообщения, превышающего размер строки, задайте несколько команд ECHO.
При указании команды ECHO OFF в командной строке командная подсказка не выводится на экран. Чтобы вновь ее увидеть, наберите ECHO ON.
Для предотвращения эхоотображения конкретной строки вы можете задать перед ней в командном файле символ @. Чтобы отобразить на экране пустую строку, наберите команду ECHO с точкой (ECHO.). Пробел между ними не указывается.
При использовании команды ECHO нельзя указывать символ конвейеризации (|) или перенаправления (< или >).
Echo что за команда
Внутренняя команда — это команда, которая встроена непосредственно в Bash. Команды делаются встроенными либо из соображений производительности — встроенные команды исполняются быстрее, чем внешние, которые, как правило, запускаются в дочернем процессе, либо из-за необходимости прямого доступа к внутренним структурам командного интерпретатора.
Действие, когда какая либо команда или сама командная оболочка инициирует ( порождает ) новый подпроцесс, что бы выполнить какую либо работу, называется ветвлением ( forking ) процесса. Новый процесс называется «дочерним» (или «потомком»), а породивший его процесс — «родительским» (или «предком»). В результате и потомок и предок продолжают исполняться одновременно — параллельно друг другу. В общем случае, встроенные команды Bash, при исполнении внутри сценария, не порождают новый подпроцесс, в то время как вызов внешних команд, как правило, приводит к созданию нового подпроцесса.
Внутренние команды могут иметь внешние аналоги. Например, внутренняя команда Bash — echo имеет внешний аналог /bin/echo и их поведение практически идентично.
#!/bin/bash echo "Эта строка выводится внутренней командой \"echo\"." /bin/echo "А эта строка выводится внешней командой the /bin/echo."
Ввод/вывод echo выводит (на stdout) выражение или содержимое переменной (см. Пример 4-1).
echo Hello echo $a
Для вывода экранированных символов, echo требует наличие ключа -e. См. Пример 5-2. Обычно, командв echo выводит в конце символ перевода строки. Подавить вывод это символа можно ключом -n.
if echo "$VAR" | grep -q txt # if [[ $VAR = *txt* ]] then echo "$VAR содержит подстроку \"txt\"" fi
| Кроме того, команда echo, в комбинации с подстановкой команд может учавствовать в операции присвоения значения переменной. a=`echo «HELLO» | tr A-Z a-z` См. так же Пример 12-15, Пример 12-2, Пример 12-32 и Пример 12-33. |
Следует запомнить, что команда echo `command` удалит все символы перевода строки, которые будут выведены командой command. Переменная $IFS обычно содержит символ перевода строки \n , как один из вариантов пробельного символа. Bash разобьет вывод команды command, по пробельным символам, на аргументы и передаст их команде echo, которая выведет эти аргументы, разделенные пробелами.
bash$ ls -l /usr/share/apps/kjezz/sounds -rw-r--r-- 1 root root 1407 Nov 7 2000 reflect.au -rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au bash$ echo `ls -l /usr/share/apps/kjezz/sounds` total 40 -rw-r--r-- 1 root root 716 Nov 7 2000 reflect.au -rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au
bash$ type -a echo echo is a shell builtin echo is /bin/echo
printf printf — команда форматированного вывода, расширенный вариант команды echo и ограниченный вариант библиотечной функции printf() в языке C, к тому же синтаксис их несколько отдичается друг от друга. printf format-string. parameter. Это встроенная команда Bash. Имеет внешний аналог /bin/printf или /usr/bin/printf. За более подробной информацией обращайтесь к страницам справочного руководства man 1 printf по системным командам.
| Старые версии Bash могут не поддерживать команду printf. |
Пример 11-1. printf в действии
#!/bin/bash # printf demo # От переводчика: # Считаю своим долгом напомнить, что в качестве разделителя дробной и целой # частей в вещественных числах, может использоваться символ "запятая" # (в русских локалях), поэтому данный сценарий может выдавать сообщение # об ошибке (у меня так и произошло) при выводе числа PI. # Тогда попробуйте заменить в определении числа PI десятичную точку # на запятую -- это должно помочь. ;-) PI=3,14159265358979 DecimalConstant=31373 Message1="Поздравляю," Message2="Землянин." echo printf "Число пи с точностью до 2 знака после запятой = %1.2f" $PI echo printf "Число пи с точностью до 9 знака после запятой = %1.9f" $PI # Даже округляет правильно. printf "\n" # Перевод строки, printf "Константа = \t%d\n" $DecimalConstant # Вставлен символ табуляции (\t) printf "%s %s \n" $Message1 $Message2 echo # ==========================================# # Эмуляция функции 'sprintf' в языке C. # Запись форматированной строки в переменную. echo Pi12=$(printf "%1.12f" $PI) echo "Число пи с точностью до 12 знака после запятой = $Pi12" Msg=`printf "%s %s \n" $Message1 $Message2` echo $Msg; echo $Msg exit 0
Одно из полезных применений команды printf — форматированный вывод сообщений об ошибках
E_BADDIR=65 var=nonexistent_directory error() < printf "$@" >&2 # Форматированный вывод аргументов на stderr. echo exit $E_BADDIR > cd $var || error $"Невозможно перейти в каталог %s." "$var" # Спасибо S.C.
Пример 11-2. Ввод значений переменных с помощью read
#!/bin/bash echo -n "дите значение переменной 'var1': " # Ключ -n подавляет вывод символа перевода строки. read var1 # Обратите внимание -- перед именем переменной отсутствует символ '$'. echo "var1 = $var1" echo # Одной командой 'read' можно вводить несколько переменных. echo -n "дите значения для переменных 'var2' и 'var3' (через пробел или табуляцию): " read var2 var3 echo "var2 = $var2 var3 = $var3" # Если было введено значение только одной переменной, то вторая останется "пустой". exit 0
Пример 11-3. Пример использования команды read без указания переменной для ввода
#!/bin/bash echo # -------------------------- # # Первый блок кода. echo -n "Введите значение: " read var echo "\"var\" = "$var"" # Здесь нет ничего неожиданного. # -------------------------- # echo echo -n "Введите другое значение: " read # Команда 'read' употребляется без указания переменной для ввода, #+ тем не менее. #+ По-умолчанию ввод осуществляется в переменную $REPLY. var="$REPLY" echo "\"var\" = "$var"" # Эта часть сценария эквивалентна первому блоку, выделенному выше. echo exit 0
Обычно, при вводе в окне терминала с помощью команды «read», символ \ служит для экранирования символа перевода строки. Ключ -r заставляет интерпретировать символ \ как обычный символ.
Пример 11-4. Ввод многострочного текста с помощью read
#!/bin/bash echo echo "Введите строку, завершающуюся символом \\, и нажмите ENTER." echo "Затем введите вторую строку, и снова нажмите ENTER." read var1 # При чтении, символ "\" экранирует перевод строки. # первая строка \ # вторая строка echo "var1 = $var1" # var1 = первая строка вторая строка # После ввода каждой строки, завершающейся символом "\", # вы можете продолжать ввод на другой строке. echo; echo echo "Введите другую строку, завершающуюся символом \\, и нажмите ENTER." read -r var2 # Ключ -r заставляет команду "read" воспринимать "\" # как обычный символ. # первая строка \ echo "var2 = $var2" # var2 = первая строка \ # Ввод данных прекращается сразу же после первого нажатия на клавишу ENTER. echo exit 0
Команда read имеет ряд очень любопытных опций, которые позволяют выводить подсказку — приглашение ко вводу (prompt), и даже читать данные не дожидаясь нажатия на клавишу ENTER.
# Чтение данных, не дожидаясь нажатия на клавишу ENTER. read -s -n1 -p "Нажмите клавишу " keypress echo; echo "Была нажата клавиша "\"$keypress\""." # -s -- подавляет эхо-вывод, т.е. ввод с клавиатуры не отображается на экране. # -n N -- ввод завершается автоматически, сразу же после ввода N-го символа. # -p -- задает вид строки подсказки - приглашения к вводу (prompt). # Использование этих ключей немного осложняется тем, что они должны следовать в определенном порядке.
Ключ -n, кроме всего прочего, позволяет команде read обнаруживать нажатие курсорных и некоторых других служебных клавиш.
Пример 11-5. Обнаружение нажатия на курсорные клавиши
#!/bin/bash # arrow-detect.sh: Обнаружение нажатия на курсорные клавиши, и не только. # Спасибо Sandro Magi за то что показал мне -- как. # -------------------------------------------- # Коды клавиш. arrowup='\[A' arrowdown='\[B' arrowrt='\[C' arrowleft='\[D' insert='\[2' delete='\[3' # -------------------------------------------- SUCCESS=0 OTHER=65 echo -n "Нажмите на клавишу. " # Может потребоваться нажать на ENTER, если была нажата клавиша # не входящая в список выше. read -n3 key # Прочитать 3 символа. echo -n "$key" | grep "$arrowup" #Определение нажатой клавиши. if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \"." exit $SUCCESS fi echo -n "$key" | grep "$arrowdown" if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \" exit $SUCCESS fi echo -n "$key" | grep "$arrowrt" if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \"О\"." exit $SUCCESS fi echo -n "$key" | grep "$arrowleft" if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \"." exit $SUCCESS fi echo -n "$key" | grep "$insert" if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \"Insert\"." exit $SUCCESS fi echo -n "$key" | grep "$delete" if [ "$?" -eq $SUCCESS ] then echo "Нажата клавиша \"Delete\"." exit $SUCCESS fi echo " Нажата какая-то другая клавиша." exit $OTHER # Упражнения: # --------- # 1) Упростите сценарий, заменив множество if-ов #+ одной конструкцией 'case'. # 2) Добавьте определение нажатий на клавиши "Home", "End", "PgUp" и "PgDn".
Ключ -t позволяет ограничивать время ожидания ввода командой read (см. Пример 9-4). Команда read может считывать значения для переменных из файла, перенаправленного на stdin. Если файл содержит не одну строку, то переменной будет присвоена только первая строка. Если команде read будет передано несколько переменных, то первая строка файла будет разбита, по пробелам, на несколько подстрок, каждая из которых будет записана в свою переменную. Будьте осторожны!
Пример 11-6. Чтение командой read из файла через перенаправление
#!/bin/bash read var1cat file1 file2 | while read line do echo $line doneФайловая система cd Уже знакомая нам команда cd, изменяющая текущий каталог, может быть использована в случаях, когда некоторую команду необходимо запустить только находясь в определенном каталоге.
(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)bash$ cd // bash$ pwd //Само собой разумеется, это должен был бы быть каталог /. Эта проблема наблюдается как в командной строке, так и в сценариях.
pwd Выводит название текущего рабочего каталога (Print Working Directory) (см. Пример 11-7). Кроме того, имя текущего каталога хранится во внутренней переменной $PWD. pushd, popd, dirs Этот набор команд является составной частью механизма "закладок" на каталоги и позволяет перемещаться по каталогам вперед и назад в заданном порядке. Для хранения имен каталогов используется стек (LIFO -- "последний вошел, первый вышел"). pushd dir-name -- помещает имя текущего каталога в стек и осуществляет переход в каталог dir-name. popd -- выталкивает, находящееся на вершине стека, имя каталога и одновременно осуществляет переход в каталог, оказавшийся на врешине стека. dirs -- выводит содержимое стека каталогов (сравните с переменной $DIRSTACK). В случае успеха, обе команды -- pushd и popd автоматически вызывают dirs. Эти команды могут оказаться весьма полезными, когда в сценарии нужно производить частую смену каталогов, но при этом не хочется жестко "зашивать" имена каталогов. Обратите внимание: содержимое стека каталогов постоянно хранится в переменной-массиве -- $DIRSTACK.
Пример 11-7. Смена текущего каталога
#!/bin/bash dir1=/usr/local dir2=/var/spool pushd $dir1 # Команда 'dirs' будет вызвана автоматически (на stdout будет выведено содержимое стека). echo "Выполнен переход в каталог `pwd`." # Обратные одиночные кавычки. # Теперь можно выполнить какие либо действия в каталоге 'dir1'. pushd $dir2 echo "Выполнен переход в каталог `pwd`." # Теперь можно выполнить какие либо действия в каталоге 'dir2'. echo "На вершине стека находится: $DIRSTACK." popd echo "Возврат в каталог `pwd`." # Теперь можно выполнить какие либо действия в каталоге 'dir1'. popd echo "Возврат в первоначальный рабочий каталог `pwd`." exit 0Переменные let Команда let производит арифметические операции над переменными. В большинстве случаев, ее можно считать упрощенным вариантом команды expr.
Пример 11-8. Команда let, арифметические операции.
#!/bin/bash echo let a=11 # То же, что и 'a=11' let a=a+5 # Эквивалентно "a = a + 5" # (Двойные кавычки и дополнительные пробелы делают код более удобочитаемым) echo "11 + 5 = $a" let "a eval eval arg1 [arg2] . [argN] Транслирует список аргументов, из списка, в команды. Пример 11-9. Демонстрация команды eval#!/bin/bash y=`eval ls -l` # Подобно y=`ls -l` echo $y # но символы перевода строки не выводятся, поскольку имя переменной не в кавычках. echo echo "$y" # Если имя переменной записать в кавычках -- символы перевода строки сохраняются. echo; echo y=`eval df` # Аналогично y=`df` echo $y # но без символов перевода строки. # Когда производится подавление вывода символов LF (перевод строки), то анализ #+ результатов различными утилитами, такими как awk, можно сделать проще. exit 0Пример 11-10. Принудительное завершение сеанса
#!/bin/bash y=`eval ps ax | sed -n '/ppp/p' | awk '< print $1 >'` # Выяснить PID процесса 'ppp'. kill -9 $y # "Прихлопнуть" его # Предыдущие строки можно заменить одной строкой # kill -9 `ps ax | awk '/ppp/ < print $1 >' chmod 666 /dev/ttyS3 # Завершенный, по сигналу SIGKILL, ppp изменяет права доступа # к последовательному порту. Вернуть их в первоначальное состояние. rm /var/lock/LCK..ttyS3 # Удалить lock-файл последовательного порта. exit 0Пример 11-11. Шифрование по алгоритму "rot13"
#!/bin/bash # Реализация алгоритма шифрования "rot13" с помощью 'eval'. # Сравните со сценарием "rot13.sh". setvar_rot_13() # Криптование по алгоритму "rot13" < local varname=$1 varvalue=$2 eval $varname='$(echo "$varvalue" | tr a-z n-za-m)' >setvar_rot_13 var "foobar" # Пропустить слово "foobar" через rot13. echo $var # sbbone echo $var | tr a-z n-za-m # foobar # Расшифровывание. # Пример предоставил Stephane Chazelas. exit 0Rory Winston представил следующий пример, как образец практического использования команды eval.
Пример 11-12. Замена имени переменной на ее значение, в исходном тексте программы на языке Perl, с помощью eval
В программе "test.pl", на языке Perl: . my $WEBROOT = ; . Эта попытка подстановки значения переменной вместо ее имени: $export WEBROOT_PATH=/usr/local/webroot $sed 's//$WEBROOT_PATH/' < test.pl >out даст такой результат: my $WEBROOT = $WEBROOT_PATH; Тем не менее: $export WEBROOT_PATH=/usr/local/webroot $eval sed 's//$WEBROOT_PATH/' < test.pl >out # ==== Этот вариант дал желаемый результат -- имя переменной, в тексте программы, благополучно было заменено на ее значение: my $WEBROOT = /usr/local/webroot
| Команда eval может быть небезопасна. Если существует приемлемая альтернатива, то желательно воздерживаться от использования eval. Так, eval $COMMANDS исполняет код, который записан в переменную COMMANDS, которая, в свою очередь, может содержать весьма неприятные сюрпризы, например rm -rf *. Использование команды eval, для исполнения кода неизвестного происхождения, крайне опасно. |
set Команда set изменяет значения внутренних переменных сценария. Она может использоваться для переключения опций (ключей, флагов), определяющих поведение скрипта. Еще одно применение -- сброс/установка позиционных параметров (аргументов), значения которых будут восприняты как результат работы команды ( set `command`).
Пример 11-13. Установка значений аргументов с помощью команды set
#!/bin/bash # script "set-test" # Вызовите сценарий с тремя аргументами командной строки, # например: "./set-test one two three". echo echo "Аргументы перед вызовом set \`uname -a\` :" echo "Аргумент #1 = $1" echo "Аргумент #2 = $2" echo "Аргумент #3 = $3" set `uname -a` # Изменение аргументов # значения которых берутся из результата работы `uname -a` echo $_ echo "Аргументы после вызова set \`uname -a\` :" # $1, $2, $3 и т.д. будут переустановлены в соответствии с выводом #+ команды `uname -a` echo "Поле #1 'uname -a' = $1" echo "Поле #2 'uname -a' = $2" echo "Поле #3 'uname -a' = $3" echo --- echo $_ # --- echo exit 0
bash$ set AUTHORCOPY=/home/bozo/posts BASH=/bin/bash BASH_VERSION=$'2.05.8(1)-release' . XAUTHORITY=/home/bozo/.Xauthority _=/etc/bashrc variable22=abc variable23=xzy
Если команда set используется с ключом " --" , после которого следует переменная, то значение переменной переносится в позиционные параметры (аргументы). Если имя переменной отсутствует, то эта команда приводит к сбросу позиционных параметров.
Пример 11-14. Изменение значений позиционных параметров (аргументов)
#!/bin/bash variable="one two three four five" set -- $variable # Значения позиционных параметров берутся из "$variable". first_param=$1 second_param=$2 shift; shift # сдвиг двух первых параметров. remaining_params="$*" echo echo "первый параметр = $first_param" # one echo "второй параметр = $second_param" # two echo "остальные параметры = $remaining_params" # three four five echo; echo # Снова. set -- $variable first_param=$1 second_param=$2 echo "первый параметр = $first_param" # one echo "второй параметр = $second_param" # two # ====================================================== set -- # Позиционные параметры сбрасываются, если не задано имя переменной. first_param=$1 second_param=$2 echo "первый параметр = $first_param" # (пустое значение) echo "второй параметр = $second_param" # (пустое значение) exit 0
См. так же Пример 10-2 и Пример 12-40. unset Команда unset удаляет переменную, фактически -- устанавливает ее значение в null . Обратите внимание: эта команда не может сбрасывать позиционные параметры (аргументы).
bash$ unset PATH bash$ echo $PATH bash$
Пример 11-15. "Сброс" переменной
#!/bin/bash # unset.sh: Сброс переменной. variable=hello # Инициализация. echo "variable = $variable" unset variable # Сброс. # Тот же эффект дает variable= echo "(unset) variable = $variable" # $variable = null. exit 0
export Команда export экспортирует переменную, делая ее доступной дочерним процессам. К сожалению, невозможно экспортировать переменную родительскому процессу. В качестве примера использования команды export можно привести сценарии инициализации системы, вызываемые в процессе загрузки, которые инициализируют и экспортируют переменные окружения, делая их доступными для пользовательских процессов.
Пример 11-16. Передача переменных во вложенный сценарий awk, с помощью export
#!/bin/bash # Еще одна версия сценария "column totaler" (col-totaler.sh) # который суммирует заданную колонку (чисел) в заданном файле. # Здесь используются переменные окружения, которые передаются сценарию 'awk'. ARGS=2 E_WRONGARGS=65 if [ $# -ne "$ARGS" ] # Проверка количества входных аргументов. then echo "Порядок использования: `basename $0` filename column-number" exit $E_WRONGARGS fi filename=$1 column_number=$2 #===== До этой строки идентично первоначальному варианту сценария =====# export column_number # Экспорт номера столбца. # Начало awk-сценария. # ------------------------------------------------ awk ' < total += $ENVIRON["column_number"] >END < print total >' $filename # ------------------------------------------------ # Конец awk-сценария. # Спасибо Stephane Chazelas. exit 0
bash$ export var=(a b); echo $ (a b) bash$ var=(a b); export var; echo $ a
declare, typeset Команды declare и typeset задают и/или накладывают ограничения на переменные. readonly То же самое, что и declare -r, делает переменную доступной только для чтения, т.е. переменная становится подобна константе. При попытке изменить значение такой переменной выводится сообщение об ошибке. Эта команда может расцениваться как квалификатор типа const в языке C. getopts Мощный инструмент, используемый для разбора аргументов, передаваемых сценарию из командной строки. Это встроенная команда Bash, но имеется и ее "внешний" аналог /usr/bin/getopt, а так же программистам, пишущим на C, хорошо знакома похожая библиотечная функция getopt. Она позволяет обрабатывать серии опций, объединенных в один аргумент [2] и дополнительные аргументы, передаваемые сценарию (например, scriptname -abc -e /usr/local). С командой getopts очень тесно взаимосвязаны скрытые переменные. $OPTIND -- указатель на аргумент ( OPTion INDex) и $OPTARG ( OPTion ARGument) -- дополнительный аргумент опции. Символ двоеточия, следующий за именем опции, указывает на то, что она имеет дополнительный аргумент. Обычно getopts упаковывается в цикл while, в каждом проходе цикла извлекается очередная опция и ее аргумент (если он имеется), обрабатывается, затем уменьшается на 1 скрытая переменная $OPTIND и выполняется переход к началу новой итерации.
while getopts ":abcde:fg" Option # Начальное объявление цикла анализа опций. # a, b, c, d, e, f, g -- это возможные опции (ключи). # Символ : после опции 'e' указывает на то, что с данной опцией может идти # дополнительный аргумент. do case $Option in a ) # Действия, предусмотренные опцией 'a'. b ) # Действия, предусмотренные опцией 'b'. . e) # Действия, предусмотренные опцией 'e', а так же необходимо обработать $OPTARG, # в которой находится дополнительный аргумент этой опции. . g ) # Действия, предусмотренные опцией 'g'. esac done shift $(($OPTIND - 1)) # Перейти к следующей опции. # Все не так сложно, как может показаться ;-)
Пример 11-17. Прием опций/аргументов, передаваемых сценарию, с помощью getopts
#!/bin/bash # ex33.sh # Обработка опций командной строки с помощью 'getopts'. # Попробуйте вызвать этот сценарий как: # 'scriptname -mn' # 'scriptname -oq qOption' (qOption может быть любой произвольной строкой.) # 'scriptname -qXXX -r' # # 'scriptname -qr' - Неожиданный результат: "r" будет воспринят как дополнительный аргумент опции "q" # 'scriptname -q -r' - То же самое, что и выше # Если опция ожидает дополнительный аргумент ("flag:"), то следующий параметр # в командной строке, будет воспринят как дополнительный аргумент этой опции. NO_ARGS=0 E_OPTERROR=65 if [ $# -eq "$NO_ARGS" ] # Сценарий вызван без аргументов? then echo "Порядок использования: `basename $0` options (-mnopqrs)" exit $E_OPTERROR # Если аргументы отсутствуют -- выход с сообщением # о порядке использования скрипта fi # Порядок использования: scriptname -options # Обратите внимание: дефис (-) обязателен while getopts ":mnopq:rs" Option do echo $OPTIND case $Option in m ) echo "Сценарий #1: ключ -m-";; n | o ) echo "Сценарий #2: ключ -$Option-";; p ) echo "Сценарий #3: ключ -p-";; q ) echo "Сценарий #4: ключ -q-, с аргументом \"$OPTARG\"";; # Обратите внимание: с ключом 'q' должен передаваться дополнительный аргумент, # в противном случае отработает выбор "по-умолчанию". r | s ) echo "Сценарий #5: ключ -$Option-"'';; * ) echo "Выбран недопустимый ключ.";; # ПО-УМОЛЧАНИЮ esac done shift $(($OPTIND - 1)) # Переход к очередному параметру командной строки. exit 0
Когда эта команда вызывается из командной строки, то это приводит к запуску указанного сценария. Внутри сценария, команда source file-name загружает файл file-name. Таким образом она очень напоминает директиву препроцессора языка C/C++ -- "#include". Может найти применение в ситуациях, когда несколько сценариев пользуются одним файлом с данными или библиотекой функций.
Пример 11-18. "Подключение" внешнего файла
#!/bin/bash . data-file # Загрузка файла с данными. # Тот же эффект дает "source data-file", но этот вариант более переносим. # Файл "data-file" должен находиться в текущем каталоге, #+ т.к. путь к нему не указан. # Теперь, выведем некоторые переменные из этого файла. echo "variable1 (из data-file) = $variable1" echo "variable3 (из data-file) = $variable3" let "sum = $variable2 + $variable4" echo "Сумма variable2 + variable4 (из data-file) = $sum" echo "message1 (из data-file): \"$message1\"" # Обратите внимание: кавычки экранированы print_message Вызвана функция вывода сообщений, находящаяся в data-file. exit 0
Файл data-file для Пример 11-18, представленного выше, должен находиться в том же каталоге.
# Этот файл подключается к сценарию. # Подключаемые файлы могут содержать об"явления переменных, функций и т.п. # Загружаться может командой 'source' или '.' . # Инициализация некоторых переменных. variable1=22 variable2=474 variable3=5 variable4=97 message1="Привет! Как поживаете?" message2="Досвидания!" print_message ()
Сценарий может подключить даже самого себя, только этому едва ли можно найти какое либо практическое применение.
Пример 11-19. Пример (бесполезный) сценария, который подключает себя самого.
#!/bin/bash # self-source.sh: сценарий, который рекурсивно подключает себя самого." # Из "Бестолковые трюки", том II. MAXPASSCNT=100 # Максимальное количество проходов. echo -n "$pass_count " # На первом проходе выведет два пробела, #+ т.к. $pass_count еще не инициализирована. let "pass_count += 1" # Операция инкремента неинициализированной переменной $pass_count #+ на первом проходе вполне допустима. # Этот прием срабатывает в Bash и pdksh, но, #+ при переносе сценария в другие командные оболочки, #+ он может оказаться неработоспособным или даже опасным. # Лучшим выходом из положения, будет присвоить переменной $pass_count #+ значение 0, если она неинициализирована. while [ "$pass_count" -le $MAXPASSCNT ] do . $0 # "Подключение" самого себя. # ./$0 (истинная рекурсия) в данной ситуации не сработает. done # Происходящее здесь фактически не является рекурсией как таковой, #+ т.к. сценарий как бы "расширяет" себя самого #+ (добавляя новый блок кода) #+ на каждом проходе цикла 'while', #+ командой 'source' в строке 22. # # Само собой разумеется, что первая строка (#!), вновь подключенного сценария, #+ интерпретируется как комментарий, а не как начало нового сценария (sha-bang) echo exit 0 # The net effect is counting from 1 to 100. # Very impressive. # Упражнение: # ---------- # Напишите сценарий, который использовал бы этот трюк для чего либо полезного.
Безусловное завершение работы сценария. Команде exit можно передать целое число, которое будет возвращено вызывающему процессу как код завершения. Вообще, считается хорошей практикой завершать работу сценария, за исключением простейших случаев, командой exit 0, чтобы проинформировать родительский процесс об успешном завершении.
Если сценарий завершается командой exit без аргументов, то в качестве кода завершения сценария принимается код завершения последней выполненной команды, не считая самой команды exit.
Это встроенная команда интерпретатора shell, заменяет текущий процесс новым процессом, запускаемым командой exec. Обычно, когда командный интерпретатор встречает эту команду, то он порождает дочерний процесс, чтобы исполнить команду. При использовании встроенной команды exec, оболочка не порождает еще один процесс, а заменяет текущий процесс другим. Для сценария это означает его завершение сразу после исполнения команды exec. По этой причине, если вам встретится exec в сценарии, то, скорее всего это будет последняя команда в сценарии.
Пример 11-20. Команда exec
#!/bin/bash exec echo "Завершение \"$0\"." # Это завершение работы сценария. # ---------------------------------- # Следующие ниже строки никогда не будут исполнены echo "Эта строка никогда не будет выведена на экран." exit 99 # Сценарий завершит работу не здесь. # Проверьте код завершения сценария #+ командой 'echo $?'. # Он точно не будет равен 99.
Пример 11-21. Сценарий, который запускает себя самого
#!/bin/bash # self-exec.sh echo echo "Эта строка в сценарии единственная, но она продолжает выводиться раз за разом." echo "PID остался равным $$." # Демонстрация того, что команда exec не порождает дочерний процесс. echo "==================== Для завершения - нажмите Ctl-C ====================" sleep 1 exec $0 # Запуск очередного экземпляра этого же сценария #+ который замещает предыдущий. echo "Эта строка никогда не будет выведена!" # Почему? exit 0
Ключ -exec команды find -- это не то же самое, что встроенная команда exec.
Эта команда позволяет изменять ключи (опции) оболочки на лету (см. Пример 23-1 и Пример 23-2). Ее часто можно встретить в стартовых файлах, но может использоваться и в обычных сценариях. Требует Bash версии 2 или выше.
shopt -s cdspell # Исправляет незначительные орфографические ошибки в именах каталогов в команде 'cd' cd /hpme # Oops! Имелось ввиду '/home'. pwd # /home # Shell исправил опечатку.
Команда возвращает код завершения -- ноль , или успешное завершение, и ничего больше.
# Бесконечный цикл while true # вместо ":" do operation-1 operation-2 . operation-n # Следует предусмотреть способ завершения цикла. done
Возвращает код завершения, свидетельствующий о неудаче, и ничего более.
# Цикл, который никогда не будет исполнен while false do # Следующий код не будет исполнен никогда. operation-1 operation-2 . operation-n done
Очень похожа на внешнюю команду which, type cmd выводит полный путь к "cmd" . В отличие от which, type является внутренней командой Bash. С опцией -a не только различает ключевые слова и внутренние команды, но и определяет местоположение внешних команд с именами, идентичными внутренним.
bash$ type '[' [ is a shell builtin bash$ type -a '[' [ is a shell builtin [ is /usr/bin/[
Запоминает путь к заданной команде (в хэш-таблице командной оболочки), благодаря чему, при повторном обращении к ней, оболочка или сценарий уже не будет искать путь к команде в $PATH. При вызове команды hash без аргументов, просто выводит содержимое хэш-таблицы. С ключом -r -- очищает хэш-таблицу.
bash$ help exit exit: exit [n] Exit the shell with a status of N. If N is omitted, the exit status is that of the last command executed.
11.1. Команды управления заданиями
Выводит список заданий, исполняющихся в фоне. Команда ps более информативна.
Задания и процессы легко спутать. Некоторые внутренние команды, такие как kill, disown и wait принимают в качестве параметра либо номер задания, либо номер процесса. Команды fg, bg и jobs принимают только номер задания.
bash$ sleep 100 & [1] 1384 bash $ jobs
"1" -- это номер задания (управление заданиями осуществляет текущий командный интерпретатор), а "1384" -- номер процесса (управление процессами осуществляется системой). Завершить задание/процесс ("прихлопнуть") можно либо командой kill %1, либо kill 1384.
Удаляет задание из таблицы активных заданий командной оболочки.
Команда fg переводит задание из фона на передний план. Команда bg перезапускает приостановленное задание в фоновом режиме. Если эти команды были вызваны без указания номера задания, то они воздействуют на текущее исполняющееся задание.
Вы можете использовать команду wait для предотвращения преждевременного завершения сценария до того, как завершит работу фоновое задание.
Пример 11-22. Ожидание завершения процесса перед тем как продолжить работу
#!/bin/bash ROOT_UID=0 # Только пользователь с $UID = 0 имеет привилегии root. E_NOTROOT=65 E_NOPARAMS=66 if [ "$UID" -ne "$ROOT_UID" ] then echo "Для запуска этого сценария вы должны обладать привилегиями root." exit $E_NOTROOT fi if [ -z "$1" ] then echo "Порядок использования: `basename $0` имя-файла" exit $E_NOPARAMS fi echo "Обновляется база данных 'locate'. " echo "Это может занять продолжительное время." updatedb /usr & # Должна запускаться с правами root. wait # В этом месте сценарий приостанавливает свою работу до тех пор, пока не отработает 'updatedb'. # Желательно обновить базу данных перед тем как выполнить поиск файла. locate $1 # В худшем случае, без команды wait, сценарий завершил бы свою работу до того, # как завершила бы работу утилита 'updatedb', # сделав из нее "осиротевший" процесс. exit 0
При запуске команды в фоне из сценария может возникнуть ситуация, когда сценарий приостанавливает свою работу до тех пор, пока не будет нажата клавиша ENTER. Это, кажется, происходит с командами, делающими вывод на stdout. Такое поведение может вызывать раздражение у пользователя.
#!/bin/bash # test.sh ls -l & echo "Done."
bash$ ./test.sh Done. [bozo@localhost test-scripts]$ total 1 -rwxr-xr-x 1 bozo bozo 34 Oct 11 15:09 test.sh _
Разместив команду wait, после запуска фонового задания, можно предотвратить такое поведение сценария.
#!/bin/bash # test.sh ls -l & echo "Done." wait
bash$ ./test.sh Done. [bozo@localhost test-scripts]$ total 1 -rwxr-xr-x 1 bozo bozo 34 Oct 11 15:09 test.sh
Перенаправление вывода в файл или даже на устройство /dev/null также снимает эту проблему.
Действует аналогично нажатию на комбинацию клавиш Control+- Z, за исключением того, что она приостанавливает работу командной оболочки.
Выдает статистику исполнения команд в единицах системного времени, в следующем виде:
0m0.020s 0m0.020s
Имеет весьма ограниченную сферу применения, так как сценарии крайне редко подвергаются профилированию.
Пример 11-23. Сценарий, завершающий себя сам с помощью команды kill
#!/bin/bash # self-destruct.sh kill $$ # Сценарий завершает себя сам. # Надеюсь вы еще не забыли, что "$$" -- это PID сценария. echo "Эта строка никогда не будет выведена." # Вместо него на stdout будет выведено сообщение "Terminated". exit 0 # Какой код завершения вернет сценарий? # # sh self-destruct.sh # echo $? # 143 # # 143 = 128 + 15 # сигнал TERM
Команда kill -l выведет список всех сигналов. Команда kill -9 -- это "жесткий kill" , она используется, как правило, для завершения зависших процессов, которые упорно отказываются "умирать", отвергая простой kill. Иногда достаточно подать команду kill -15. "Процессы-зомби" , т.е. процессы, "родители" которых уже завершили работу, не могут быть "убиты" таким способом (невозможно "убить" "мертвого"), рано или поздно с ними "расправится" процесс init.
Директива command COMMAND запрещает использование псевдонимов и функций с именем "COMMAND" .
Конструкция builtin BUILTIN_COMMAND запускает внутреннюю команду "BUILTIN_COMMAND" , на время запрещая использование функций и внешних системных команд с тем же именем.
Обратите внимание: autoload не является частью ядра Bash. Ее необходимо загрузить с помощью команды enable -f (см. выше).
Таблица 11-1. Идентификация заданий
| Нотация | Описание |
|---|---|
| %N | Номер задания [N] |
| %S | Вызов (командная строка) задания, которая начинается со строки S |
| %?S | Вызов (командная строка) задания, которая содержит строку S |
| %% | "текущее" задание (последнее задание приостановленное на переднем плане или запущенное в фоне) |
| %+ | "текущее" задание (последнее задание приостановленное на переднем плане или запущенное в фоне) |
| %- | Последнее задание |
| $! | Последний фоновый процесс |
Примечания
Исключение из правил -- команда time, которая в официальной документации к Bash называется ключевым словом.
Опция -- это аргумент, который управляет поведением сценария и может быть либо включен, либо выключен. Аргумент, который объединяет в себе несколько опций (ключей), определяет поведение сценария в соответствии с отдельными опциями, объединенными в данном аргументе..
Как правило, исходные тексты подобных библиотек, на языке C, располагаются в каталоге /usr/share/doc/bash-. /functions.
Обратите внимание: ключ -f команды enable может отсутствовать в некоторых системах.
| Назад | К началу | Вперед |
| Операторы выбора | Наверх | Внешние команды, программы и утилиты |