«…лишь недалекие люди боятся конкуренции, а люди подлинного творчества ценят общение с каждым талантом…» А. Бек, Талант.

Спец курс (Автоматизация процесса проектирования)/Лекция 2 (BASH) — различия между версиями

Материал из Wiki
Перейти к: навигация, поиск
(Подмножества и части строк)
(Размеры переменных)
Строка 26: Строка 26:
  
 
<source lang="bash">
 
<source lang="bash">
[root@httpd ~]$ testlength () { for p in «$@»; do echo ${#p};done }
+
#!/bin/bash
[root@httpd ~]$ testlength 1 abc «def ghi»
+
testlength () { for p in «$@»; do echo ${#p};done }
1
+
testlength 1 abc «def ghi»
3
+
#1
7
+
#3
 +
#7
 
</source>
 
</source>
 +
 
== Работа с шаблонами ==  
 
== Работа с шаблонами ==  
 
Расширение параметра также включает возможности поиска по шаблону при помощи тех же знаков подстановки, которые используются в расширениях имен файлов или подстановках. Обратите внимание, что это не соответствует регулярным выражениям, используемым grep.
 
Расширение параметра также включает возможности поиска по шаблону при помощи тех же знаков подстановки, которые используются в расширениях имен файлов или подстановках. Обратите внимание, что это не соответствует регулярным выражениям, используемым grep.

Версия 00:46, 13 февраля 2018

Лекции SCRIPT

Лекции

Практические задания
Тесты

Табель успеваемости

Экзамен

Доп. материалы

Содержание

Подмножества и части строк

  • Подмножества и части строк
  • Обычно расширение имеет такую форму: ${PARAMETER:OFFSET:LENGTH}, где аргумент LENGTH необязателен. Итак, если вы хотите выбрать только определенное подмножество аргументов скрипта, вы можете использовать полную версию, чтобы показать, сколько аргументов следует выбрать. Например, ${@:4:3} обращается к трем аргументам, начиная с аргумента 4, а именно, к аргументам 4, 5 и 6. Вы можете использовать это расширение для выбора конкретных параметров помимо тех, которые доступны сразу, используя от $1 до $9 включительно. ${@:15:1} — способ вызова сразу 15 параметра.
  • Вы можете использовать расширение с конкретными параметрами, а также весь набор параметров, представленный при помощи $* или $@. В этом случае параметр обрабатывается как строка и число, представляющее собой сдвиг или длину. Например, если переменная x имеет значение «some value», то
${x:3:5}

будет иметь значение «e val».

Подстроки значений параметров в shell

#!/bin/bash
x=»some value»
echo «${x:3:5}»
e val

Размеры переменных

  • Вы уже видели, что $# указывает число параметров и что расширение ${PARAMETER:OFFSET:LENGTH} применяется и к конкретным параметрам, и к $* и $@, поэтому вас не должно удивить, что аналогичная конструкция, ${#PARAMETER}, может использоваться для определения размера конкретного параметра. Простая функция testlength, показанная в Листинге 10, иллюстрирует это. Попробуйте сделать это сами.

#!/bin/bash
testlength () { for p in «$@»; do echo ${#p};done }
testlength 1 abc «def ghi»
#1
#3
#7

Работа с шаблонами

Расширение параметра также включает возможности поиска по шаблону при помощи тех же знаков подстановки, которые используются в расширениях имен файлов или подстановках. Обратите внимание, что это не соответствует регулярным выражениям, используемым grep.

Расширение шаблонов в shell Расширение Назначение

  • ${ПАРАМЕТР#СЛОВО} Shell расширяет СЛОВО как расширение имени файла и удаляет самое короткое соответствие шаблону, если оно имеется, с начала расширенного значения ПАРАМЕТРА. Использование ‘@’ или ‘$’ приводит к удалению по образцу для каждого параметра в списке.
  • ${ПАРАМЕТР##СЛОВО} Приводит к удалению самого длинного соответствия шаблону с начала вместо самого короткого.
  • ${ПАРАМЕТР%СЛОВО} Shell расширяет СЛОВО как расширение имени файла и удаляет самое короткое соответствие шаблону, если оно имеется, с конца расширенного значения ПАРАМЕТРА. Использование ‘@’ или ‘$’ приводит к удалению по образцу для каждого параметра в списке.
  • ${ПАРАМЕТР%%СЛОВО} Приводит к удалению самого длинного соответствия шаблону с конца вместо самого короткого.
  • ${ПАРАМЕТР/ОБРАЗЕЦ/ПОСЛЕДОВАТЕЛЬНОСТЬ} Shell расширяет ОБРАЗЕЦ как расширение имени файла и заменяет самое длинное соответствие шаблону, если оно имеется, расширенным значением ПАРАМЕТРА. Для соответствия образцам в начале расширенного значения ПАРАМЕТРА поставьте в начале ОБРАЗЦА # или %, если соответствие должно проверяться до конца. Если ПОСЛЕДОВАТЕЛЬНОСТЬ пуста, перемещение / может быть опущено и соответствия удаляются. Использование ‘@’ или ‘$’ приводит к замене образца для каждого параметра в списке.
  • ${ПАРАМЕТР//ОБРАЗЕЦ/ПОСЛЕДОВАТЕЛЬНОСТЬ} Выполняет замену для всех подходящих, а не только для первого.
[root@httpd ~]$ x=»a1 b1 c2 d2″
[root@httpd ~]$ echo ${x#*1}
b1 c2 d2
[root@httpd ~]$ echo ${x##*1}
c2 d2
[root@httpd ~]$ echo ${x%1*}
a1 b
[root@httpd ~]$ echo ${x%%1*}
a
[root@httpd ~]$ echo ${x/1/3}
a3 b1 c2 d2
[root@httpd ~]$ echo ${x//1/3}
a3 b3 c2 d2
[root@httpd ~]$ echo ${x//?1/z3}
z3 z3 c2 d2

Перенаправление потока вывода в файл

Bombilla amarilla - yellow Edison lamp.pngДескриптор файла -- это просто число, по которому система идентифицирует открытые файлы. Рассматривайте его как упрощенную версию указателя на файл.

  • COMMAND_OUTPUT > # Перенаправление stdout (вывода) в файл. Если файл отсутствовал, то он создается, иначе -- перезаписывается.
ls -lR > dir-tree.list
# Создает файл, содержащий список дерева каталогов.
  •  : > filename # Операция > усекает файл "filename" до нулевой длины. Если до выполнения операции файла не существовало, то создается новый файл с нулевой длиной (тот же эффект дает команда 'touch'). Символ : выступает здесь в роли местозаполнителя, не выводя ничего.
  • COMMAND_OUTPUT >> Перенаправление stdout (вывода) в файл. Создает новый файл, если он отсутствовал, иначе -- дописывает в конец файла.
  • 1>filename # Перенаправление вывода (stdout) в файл "filename".
  • 1>>filename # Перенаправление вывода (stdout) в файл "filename", файл открывается в режиме добавления.
  • 2>filename # Перенаправление stderr в файл "filename".
  • 2>>filename # Перенаправление stderr в файл "filename", файл открывается в режиме добавления.
  • &>filename # Перенаправление stdout и stderr в файл "filename".

Поток ввода

  • < FILENAME # Ввод из файла. Парная команде ">", часто встречается в комбинации с ней.

Перенаправление потоков

  • 2>&1 # Перенаправляется stderr на stdout. Сообщения об ошибках передаются туда же, куда и стандартный вывод.
  • i>&j # Перенаправляется файл с дескриптором i в j. Вывод в файл с дескриптором i передается в файл с дескриптором j.
  • >&j # Перенаправляется файл с дескриптором 1 (stdout) в файл с дескриптором j. Вывод на stdout передается в файл с дескриптором j.
  • [j]<>filename # Файл "filename" открывается на чтение и запись, и связывается с дескриптором "j". Если "filename" отсутствует, то он создается. Если дескриптор "j" не указан, то, по-умолчанию, берется дескриптор 0, stdin. Как одно из применений этого -- запись в конкретную позицию в файле.
echo 1234567890 > File    # Записать строку в файл "File".
      exec 3<> File             # Открыть "File" и связать с дескриптором 3.
      read -n 4 <&3             # Прочитать 4 символа.
      echo -n . >&3             # Записать символ точки.
      exec 3>&-                 # Закрыть дескриптор 3.
      cat File                  # ==> 1234.67890
      # Произвольный доступ, да и только!

Закрытие дескрипторов файлов

  • n<&- Закрыть дескриптор входного файла n.
  • 0<&-, <&- Закрыть stdin.
  • n>&- Закрыть дескриптор выходного файла n.
  • 1>&-, >&- Закрыть stdout.

Дочерние процессы наследуют дескрипторы открытых файлов. По этой причине и работают конвейеры. Чтобы предотвратить наследование дескрипторов -- закройте их перед запуском дочернего процесса.

# В конвейер передается только stderr.
exec 3>&1                              # Сохранить текущее "состояние" stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Закрыть дескр. 3 для 'grep' (но не для 'ls').
#              ^^^^   ^^^^
exec 3>&-                              # Теперь закрыть его для оставшейся части сценария.


Конвееры

  • | # Конвейер (канал). Универсальное средство для объединения команд в одну цепочку. Похоже на ">", но на самом деле -- более обширная. Используется для объединения команд, сценариев, файлов и программ в одну цепочку (конвейер).
cat *.txt | sort | uniq > result-file
  • Допускается перенаправление нескольких потоков в один файл.
ls -yz >> command.log 2>&1
# Сообщение о неверной опции "yz" в команде "ls" будет записано в файл "command.log".
# Поскольку stderr перенаправлен в файл.

Операции перенаправления и/или конвейеры могут комбинироваться в одной командной строке.

command < input-file > output-file
 
command1 | command2 | command3 > output-file

Генерация псевдослучайных чисел

  • $RANDOM -- внутренняя функция Bash (не константа), которая возвращает псевдослучайные целые числа в диапазоне 0 - 32767. Функция $RANDOM не должна использоваться для генераци ключей шифрования.
  • Если вам нужны случайные числа не превышающие определенного числа, воспользуйтесь оператором деления по модулю (остаток от деления).
  • Если вы желаете ограничить диапазон "снизу", то просто производите генерацию псевдослучайных чисел в цикле до тех пор, пока не получите число большее нижней границы.
#!/bin/bash
# $RANDOM возвращает различные случайные числа при каждом обращении к ней.
# Диапазон изменения: 0 - 32767 (16-битовое целое со знаком).
MAXCOUNT=10
count=1
 
echo
echo "$MAXCOUNT случайных чисел:"
echo "-----------------"
while [ "$count" -le $MAXCOUNT ]      # Генерация 10 ($MAXCOUNT) случайных чисел.
do
  number=$RANDOM
  echo $number
  let "count += 1"  # Нарастить счетчик.
done
echo "-----------------"


Завершение и код завершения

  • ...эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею. Chet Ramey
  • Команда exit может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом.
  • Каждая команда возвращает код завершения (иногда код завершения называют возвращаемым значением ). В случае успеха команда должна возвращать 0, а в случае ошибки -- ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты UNIX возвращают 0 в случае успешного завершения, но имеются и исключения из правил.
  • Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn, где nnn -- это код возврата (число в диапазоне 0 - 255).
  • Bombilla amarilla - yellow Edison lamp.pngNote : Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом возврата последней исполненной командой.


Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается "значение, возвращаемое" функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии.

Пример. Завершение / код завершения
#!/bin/bash
 
echo hello
echo $?    # код возврата = 0, поскольку команда выполнилась успешно.
 
lskdf      # Несуществующая команда.
echo $?    # Ненулевой код возврата, поскольку команду выполнить не удалось.
 
echo
 
exit 113   # Явное указание кода возврата 113.
           # Проверить можно, если набрать в командной строке "echo $?"
           # после выполнения этого примера.
 
#  В соответствии с соглашениями, 'exit 0' указывает на успешное завершение,
#+ в то время как ненулевое значение означает ошибку.
Переменная $? особенно полезна, когда необходимо проверить результат исполнения команды (см. Пример 12-27 и Пример 12-13).

Note Символ !, может выступать как логическое "НЕ" для инверсии кода возврата.

Пример 6-2. Использование символа ! для логической инверсии кода возврата

true  # встроенная команда "true".
echo "код возврата команды \"true\" = $?"     # 0
 
! true
echo "код возврата команды \"! true\" = $?"   # 1
# Обратите внимание: символ "!" от команды необходимо отделять пробелом.
#    !true   вызовет сообщение об ошибке "command not found"