You are on page 1of 16

03.07.

2017 Конспект по Bash ­ Codeguida

Якщо ви працюєте в ІТ, то як ніхто знаєте про ціну часу. Оптимізація робочого
процесу ­ один з найважливіших аспектів роботи в ІТ. Так чи інакше, наша
робота (будь то верстка сайту, написання модулів, чи тестування додатків)
вимагає повторення одних і тих самих дій: швидкі скріншоти з завантаженням
на сервер, обробка виділеного тексту, конвертація файлів, парсинг даних та
багато іншого. Аби не робити зайвих дій, а сконцентруватись на ідеї та самій
суті її реалізації, ще в 1978 році Стівен Борн розробив командну оболонку [sh]
[wiki­sh], яка згодом, в 1987 році була вдосконалена Браяном Фоксом і
переросла в те, що ми знаємо сьогодні як [bash][wiki­bash] (Bourne again shell).

Цілком логічно, що з’являється запитання: "Для чого мені потрібне щось, що
написали майже півстоліття тому?" Так от відповідь на нього проста: це "щось"
дотепер є найпотужнішим інструментом автоматизації та, де­факто,
стандартом для написання простих, але ефективних сценаріїв на всіх unix­
based системах. Саме тому знати загальний синтаксис bash та вміти писати на
ньому ­ критичний скіл для розробника.

В цьому пості я опишу синтаксичні конструкції, наведу приклади простих
сценаріїв та вкажу на деякі підводні камені в bash. Впевнений, що такий
конспект обов’язково стане в нагоді як початківцям, так і досвідченим
розробникам, які могли забути деякі особливості цієї надпотужної командної
оболонки.

Оболонки та виклик сценаріїв
Користувацька оболонка bash може працювати в двох режимах ­
інтерактивному та, відповідно, неінтерактивному. Відкрити оболонку в Ubuntu
можна комбінацією клавіш  Ctrl + Alt + F1 , звичний графічний інтерфейс
зникне, а перед вами відкриється один з семи віртуальних терміналів,
доступних в дистрибутиві Ubuntu. Якщо оболонка видає запрошення (щось на
зразок того, яке можна побачити нижче), то ви працюєте в інтерактивному
режимі:

https://codeguida.com/post/270 1/16
03.07.2017 Конспект по Bash ­ Codeguida

user@host:~$ 

Тут можна вводити найрізноманітніші unix­команди (як
от: ls, grep, cd, mkdir, rm) і бачити результат їх виконання. Інтерактивною ця
оболонка називається тому, що вона взаємодіє з користувачем напряму.
Оточення робочого столу (графічний інтерфейс), в сімействі систем Debian (до
яких належить і Ubuntu), прийнято розміщувати в сьомому віртуальному
терміналі, тому щоб повернутись до звичного оточення робочого столу
наберіть комбінацію  Ctrl + Alt + F7 .

Звісно працювати в віртуальних терміналах не надто зручно, особливо, якщо
потрібно редагувати документ та водночас виконувати які­небудь команди,
тому надалі ми користуватимемось вбудованим в графічний інтерфейс
емулятором віртуального терміналу, вбудованим в Ubuntu. Відкрити його
можна комбінацією клавіш  Ctrl + Alt + T , або з Unity Dash, знайшовши його
в списку програм.

В неінтерактивному режимі оболонка читає команди з деякого файлу і
послідовно виконує їх. Коли інтерпретатор дійде до кінця файлу, робота з
оболонкою автоматично завершиться. Запустити оболонку в
неінтерактивному режимі можна з допомогою команд:

sh скрипт 
bash скрипт 

Де  скрипт  це шлях до файлу, що містить команди для виконання. Такий


файл є звичайним текстовим документом, який можна створити з допомогою
будь­якого текстового документу. Втім, можна спростити виклик скрипту всього
лише зробивши його виконуваним. Для цього необхідно надати відповідні
права доступу цьому файлу з допомогою команди chmod:

https://codeguida.com/post/270 2/16
03.07.2017 Конспект по Bash ­ Codeguida

chmod +x скрипт 

Окрім цього, в першому рядку скрипта необхідно вказати яка оболонка
повинна виконувати цей сценарій. Це можна зробити, розмістивши на початку
відповідну вказівку  #!/bin/sh  (для оболонки sh) або  #!/bin/bash (відповідно
для bash). Після цього файл можна буде викликати на виконання звернувшись
до нього в терміналі:

./скрипт 

Коментарі
Сценарії можуть містити коментарі. Коментарі ­ це оператори, які можна
розміщувати в сценарії оболонки, але який ігнорується при виконанні.
Коментарі повинні починатись з символу  #  і продовжуються до символу
нового рядка.Наприклад:

#!/bin/bash 
# Сценарій, що виведе ім’я користувача 
whoami 

Змінні
Оболонка дозволяє створювати та видаляти змінні, а також виконувати над
ними операції. Змінні в bash можуть знаходитись в 3­х областях видимості:

Локальні змінні ­ це звичайні змінні в всередині одного сценарію. Вони не
доступні іншим програмам та сценаріям, які запускаються з цієї оболонки.
Оголошуються змінні з допомогою символу  = (зверніть увагу на те, що перед

https://codeguida.com/post/270 3/16
03.07.2017 Конспект по Bash ­ Codeguida

і після  =  немає пробілів), а до їх значення звертаються з допомогою
символу  $ :

name="Петро Петрович" 
echo $name    # вивід значення 
unset name    # видалення змінної 

Також можна оголосити локальну змінну всередині функції і яка буде доступна
лише в тілі цієї функції:

local локальна_змінна=значення 

Змінні оточення ­ це змінні, які доступні будь­яким програмам, що запущені з
данної оболонки. Оголошуються вони так само як і локальні змінні, але з
командою  export :

export глобальна_змінна=значення 

В bash є багато змінних оточення, які досить часто зустрічаються в сценаріях,
наприклад:

HOME ­ шлях до домашнього каталогу користувача;
PATH ­ список каталогів, в яких оболонка шукає виконувані файли;
PWD ­ шлях до робочого каталогу;

RANDOM ­ формує ціле випадкове число;
HOSTNAME ­ ім’я комп’ютера, на якому виконується оболонка;

Детальніше про змінні оточення можна почитати [тут][env­vars].

https://codeguida.com/post/270 4/16
03.07.2017 Конспект по Bash ­ Codeguida

Змінні оболонки ­ це змінні, які встановлюються оболонкою і необхідні їй для
коректної роботи. Ці змінні мають імена порядкового номера ( $1 ,  $2 ,  $3 ,
...) і містять аргументи, які передавались сценарію при запуску, як от:

./some_script.sh VAL1 VAL2  # всередині сценарію $1='VAL1', $2='VAL2' 

Змінним можна присвоювати значення за замовчуванням таким чином:

: ${VAR:='значення за замовчуванням'} # Якщо змінна VAR порожня, присвоїти 
їй "значення за замовчуванням" 

Масиви та списки
В bash також є можливість працювати з масивами. При роботі з масивами
часто користуються змінною оточення IFS ­ роздільника полів для вхідних
рядків (IFS ­ Input Field Separator). За замовчуванням IFS рівний пробільному
символу, але може бути змінений для розбиття рядка на елементи масиву,
наприклад, за комами. Зверніть увагу, що для формування змінних оболонки,
які доступні через  $1 ,  $2  і т.д., використовується саме змінна IFS, тобто
введений після ім’я скрипта рядок аргументів, буде розділений саме за
першим символом, який зберігається в цій змінній.

Оголосити масив можна наступним чином:

files[0]=Яблуко 
files[1]=Груша 
echo ${files[*]}    # надрукує елементи масиву без врахування IFS 
echo ${files[@]}    # надрукує елементи масиву з IFS в якості розільника 

https://codeguida.com/post/270 5/16
03.07.2017 Конспект по Bash ­ Codeguida

Отримувати доступ до елементу масиву можна з
допомогою зрізів:  ${arr:0:1} . Видалити перший елемент масиву можна з
допомогою зсуву:  shift arr . Додати в елементи в масив:  arr=("${arr[@]}"
"Item 1" "Item 2") . Перевірити входження елементу в масив реалізується з
допомогою дещо складнішої конструкції:

if [[ ${arr[(r)some]} == some ]]; then 
     # команди, якщо елемент входить 
else 
     # команди, якщо не входить 
fi 

В цьому прикладі  arr  ­ деякий масив, а  some  ­ це елемент, який ми


перевіряємо на входження.

Підставлення результатів операцій
Присвоїти змінній результат роботи команди чи арифметичних операцый
можна з допомогою апострофів, або конструкції  $(вираз) :

now=`data +%T` 
# або 
now=$(data +%T) 

echo now # 19:08:26 

Арифметичні операції необхідно огортати в подвійні дужки:

foo=$(( ((10 + 5*3) – 7) / 2 )) 
echo $foo    #> 9 

https://codeguida.com/post/270 6/16
03.07.2017 Конспект по Bash ­ Codeguida

З допомогою фігурних дужок можна генерувати рядки довільного вигляду, або
враховувати різні варіанти написання слова:

echo beg{i,a,u}n #> begin began begun 

Варто згадати і про строгість лапок в bash: одинарні лапки ­ строгі, подвійні ­
нестрогі. Це означає, що при підстановленні змінних в рядок з подвійними
лапками, інтерпретатор підставить відповідне значення змінної. Одинарні
лапки виведуть рядок так, як ви його написали. Приклад:

echo "Домашня директорія: $HOME"  #> Домашня директорія: /home/user 
echo 'Домашня директорія: $HOME'  #> Домашня директорія: $HOME 

Потоки
Файл з якого відбувається читання, називають стандартним потоком
введення, а в який відбувається запис, відповідно ­ стандартним потоком
виводу. В bash є три стандартних потоки:

0  stdin   ввід          
1  stdout  вивід         
2  stderr  потік помилок 

Для перенаправлення потоків використовують основні оператори:

>  ­ перенаправлення потоку виведення в файл (файл буде створений,
або перезаписаний);
>>  ­ дописати потік виведення в кінець файлу;

<  ­ перенаправляє данні з файлу в потік введення;

https://codeguida.com/post/270 7/16
03.07.2017 Конспект по Bash ­ Codeguida

<<<  ­ читання даних з рядка, замість всього вмісту файлу (працює
для bash 3+);
2>  ­ перенаправляє потік помилок в файл (файл буде створений, або
перезаписаний);
2>>  ­ дописати помилки в кінець файлу; тадада

Канали
Стандартні потоки можна перенаправляти не лише в файли, але й на вхід
інших сценаріям. З’єднання потоку виведення одної програми з потоком
введення іншої називають каналом або пайпом (pipe). Нижче наведений
простий конвеєр з трьох команд:  команда1 перенаправляє свій вивід на
вхід  команді2 , яка, в свою чергу, перенаправляє власний вивід на
вхід  команді3 :

cmd1 | cmd2 | cmd3 

Конвеєри
Конвеєри ­ це команди, що з’єднані операторами  ; ,  && ,  ||  для
виконання в певній послідовності. Оператори організації конвеєрів працюють
наступним чином:

команда1 ; команда2  ­  команда2  виконається після команди1 незалежно


від результату її роботи  команди1 ;

команда1 && команда2  ­  команда2 виконаються лише після


успішного виконання  команди1  (тобто з кодом завершення 0);

команда1 || команда2  ­  команда2  виконається лише після невдалого


виконання  команди1  (тобто код завершення  команди1  буде відмінним від
0)

https://codeguida.com/post/270 8/16
03.07.2017 Конспект по Bash ­ Codeguida

Умовні оператори
В скриптовій мові bash підтримуються два оператори
розгалуження:  if  та  case . Оператор  if , як і в інших мовах, виконує
певний блок вказівок, в залежності від умови. Умову огортають в подвійні
квадратні дужки  [[ ... ]] , які bash розглядає як один елемент з кодом
виходу. Всередині блоку операторів огорнутого в  [[ ]] дозволяється
використовувати оператори  &&  та  || . Приклади:

# Однорядковий запис 
if [ ... ]; then echo "true"; else echo "false"; fi; 

## Вкладені умови 
if [ ... ] && [ ... ]; then 
     ... 
elif [[ ... && ... ]]; then 
     ... 
else 
     ... 
fi; 

Зверніть увагу, що  [ , умова та  ]  обов’язково повинні бути розділені


пробілами, інакше оболонка сприйме в якості команди  [умова .

В нижче наведена таблиця з можливими умовами порівняння:

# Робота з файлами 
‐e    Перевірити чи існує файл чи директорія (‐f, ‐d) 
‐f    Файл існує (!‐f ‐ не існує) 
‐d    Каталог існує (!‐f ‐ не існує) 
‐s    Файл існує і він не порожній 
‐r    Файл існує і доступний для читання 
‐w    ... на запис 
‐x    ... на виконання 
‐h    Є символічним посиланням 

# Робота з рядками 
‐z    Порожній рядок 
https://codeguida.com/post/270 9/16
03.07.2017 Конспект по Bash ­ Codeguida

‐n    Не порожній рядок 
==    Рівне 
!=    Не рівне 

# Операції з числами 
‐eq   Рівне 
‐ne   Не рівне 
‐lt   Менше 
‐le   Менше або рівне 
‐gt   Більше 
‐ge   Більше або рівне 

Приклади:

if [ `uname` == "Adam"]; then 
    echo "Не їж яблуко!" 
elif [ `uname` == "Eva"] then 
    echo "Не бери яблуко!" 
else 
    echo "Яблука зараз дуже дорогі!" 
fi; 

Якщо необхідно зробити вибір з кількох альтернатив, в нагоді стане
оператор  case . Принцип його роботи найлегше зрозуміти на прикладі:

case "$extension" in 
    (jpg|jpeg) 
        echo "Це зображення у форматі jpeg." 
    ;; 
    png) 
        echо "Це зображення у форматі png" 
    ;; 
    gif) 
         echo "А це гіфочка))" 
    *) 
        echo "Оу! Це взагалі не зображення!" 
    ;; 
esac 

https://codeguida.com/post/270 10/16
03.07.2017 Конспект по Bash ­ Codeguida

В прикладі оператор перевіряє значення змінної  $extension  на співпадіння з


одним із шаблонів і у випадку співпадіння виконає відповідний блок коду. У
випадку, якщо не буде знайдено співпадінь, виконаються вказівки, що
відповідають шаблону  * .

Цикли
Мова оболонки дає користувачеві можливість організовувати циклічне
виконання інструкцій з допомогою циклів:

while

for

select

Оператор  while  описується наступним чином:

while умовa do 
     тіло 
done 

Інтерпретатор в першу чергу виконує команди, що описані в  умові . Якщо


результат виконання нульовий, то виконується тіло, а, після її виконання,
перехід до наступної ітерації, в іншому випадку відбувається вихід з циклу. В
умові може бути будь­яка допустима команда. Приклад:

#!/bin/sh 
# Квадрати чисел від 1 до 10 
x=0 
while [ $x –lt 10 ] do #значення змінної x менше 10? 
    echo $(($x*$x)) 
    x=`expr $x + 1` # збільшуємо х на 1 
done 

https://codeguida.com/post/270 11/16
03.07.2017 Конспект по Bash ­ Codeguida

Цикл  for  виконує тіло для кожного елемента зі списку. Синтаксис


циклу  for  такий:

for ім’я in елемент1 елемент2 ... елементN do 
     тіло 
done 

В якості елементів зазвичай використовують різноманітні шаблони (wildcards).
Дуже зручно застосовувати  for  для проходження по каталогах та виконання
операцій над групою файлів. В прикладі нижче, цикл проходить по всіх файлах
з розширенням  *.bash , переміщує їх в директорію  ~/scripts  та додає їх
права на виконання.

#!/bin/sh 
# Переміщення всіх скриптів з ~ в директорію ~/scripts 
for FILE in $HOME/*.bash do 
     mv $FILE ${HOME}/scripts 
     chmod +x ${HOME}/scripts/${FILE} 
done 

Цикл  select  допомагає організувати зручне меню вибору і застосовується


тоді, коли користувач повинен обрати один елемент із запропонованого
списку. Загалом цикл  select  має такий самий синтаксис як і цикл  for :

select відповідь in елемент1 елемент2 ... елементN do 
     тіло 
done 

При виконанні цього оператору, всі елементи зі списку висвічуються на екрані
зі своїми порядковими номерами у вигляді списку варіантів відповіді, після
списку виводиться спеціальне запрошення для введення. Зазвичай воно має
вигляд  #? . Введений користувачем номер списку записується в

https://codeguida.com/post/270 12/16
03.07.2017 Конспект по Bash ­ Codeguida

змінну  відповідь . Якщо  відповідь містить номер пункту меню, то в змінну


заноситься значення відповідного елементу зі списку. Якщо в списку немає
введеного пункту, список буде показаний знову. Після того, як користувач
зробить правильний вибір, виконаються вказівки в тілі, а цикл перейде до
наступної ітерації і всі дії повторяться з самого початку ­ саме тому роботу
циклу  select  бажано переривати.

#!/bin/sh 

echo ‐n "Введіть назву пакету: " && read PACKAGE 
PS3="Оберіть пакетний менеджер : " 
select ITEM in bower, npm, pip do 
     case $ITEM in 
         bower) bower install $PACKAGE ;; 
         npm) npm install $PACKAGE ;; 
         pip) pip install $PACKAGE ;; 
     esac 
     break 
done 

Приклад вище запитує в користувача назву пакету, який він бажає встановити,
далі цікавиться який пакетний менеджер використати і в залежності від вибору
встановлює потрібний пакет та зупиняє виконання.

Оболонка також має команди, для зміни нормального виконання циклу.
Оператор break повністю зупиняє виконання циклу, оператор continue ­
переходить до наступної ітерації.

Функції
В сценаріях оболонки можливе оголошення та виклик функцій. Варто
зазначити, що саме поняття функцій в bash дещо урізане. Насправді, функції в
bash ­ це іменована група команд, які виконаються під час звертання до
функції. В будь­якому випадку функціями слід користуватись всюди, де є код,
що повторюється з невеликими варіаціями.
https://codeguida.com/post/270 13/16
03.07.2017 Конспект по Bash ­ Codeguida

Оголошення функції має такий вигляд:

ім’я_функції () { 
     команди 

ім’я_функції    # звертання до функції 

Оголошення функції обов’язково повинне передувати її першому виклику.
Звертання до функції відбувається шляхом вказання її імені в якості команди.

Функція може приймати аргументи та повертати після свого виконання
результат ­ код виходу. Функція посилається до своїх аргументів точно так
само, як і до локальних змінних, з допомогою позиційних змінних ­  $1 ,  $2  і
тд. Результат роботи можна повертати з допомогою команди  return .
Наприклад, функція, яка приймає параметр (ім’я) і завершуючи свою роботу з
кодом 0:

#!/bin/sh 
#функція з параметром 
greeting() { 
     if [ ‐n "$1" ]; then 
         echo "Привіт, $1!" 
     else 
          echo "Привіт, невідомий!" 
     fi 
     return 0 

greeting користувач    #> Привіт, користувач! 
greeting               #> Привіт, невідомий! 

Команда  return  повертає код завершення 0 ­ це код успішного завершення


сценарію. Кожна програма по завершенню роботи записує в змінну
оточення  #?  код завершення ­ число від 0 до 255. З допомогою цієї змінної
можна визначати статус виконання кожної окремої команди чи скрипта. Якщо
https://codeguida.com/post/270 14/16
03.07.2017 Конспект по Bash ­ Codeguida

програма завершилась помилкою, кодом завершення буде ціле число
відмінне від нуля. Зверніть увагу, що якщо сценарій завершується
командою  exit  без параметрів, кодом завершення сценарію буде код
завершення останньої виконаної команди.

Налагодження сценаріїв
Оболонка дає кілька засобів для налагодження сценаріїв. Для активації
режиму налагодження, сценарій повинен бути запущений з допомогою
спеціальних опцій. Перший рядок сценарію повинен мати вигляд:

#!/bin/sh опция 

Можна обирати серед таких опцій:

–n  ­ читати всі команди, але не виконувати їх;

–v  ­ виводити всі рядки по мірі їх обробки інтерпретатором;

–x  ­ виводити всі команди та їх аргументи по мірі їх виконання.

Для налагодження сценарію частинами, потрібний фрагмент помічають
викликом команди  set  iз відповідною опцією з таблиці. При чому, для
увімкнення режиму налагодження, перед опцією вказують символ  ‐ , для
вимкнення режиму налагодження використовують  + :

set –x # вмиваємо режим налагоджування 
... 
set +x # вимикаємо режим налагоджування 

Загальна практика налагоджування полягає в тому, щоб перш ніж запустити
його на виконання, необхідно перевірити його синтаксис з допомогою опції  ‐

https://codeguida.com/post/270 15/16
03.07.2017 Конспект по Bash ­ Codeguida

n . Для більшої детальності можна комбінувати ключі  ‐nv . Після


виправлення синтаксичних помилок проводиться налагожування з допомогою
опції  ‐x .

Післямова
Сподіваюсь ви знайшли для себе щось нове в цьому конспекті, або,
принаймні, освіжили свої знання.

Якщо вас зацікавив скриптинг на Bash, прошу підтримати мене, поширюючи
статтю серед своїх друзів.

Радий буду почути конструктивну критику та зауваження в коментарях.

https://codeguida.com/post/270 16/16

You might also like