bash

bash (від англ. Bourne again shell , каламбур "Born again" shell - "Відроджений" shell) - вдосконалена і модернізована варіація командної оболонки Bourne shell. Одна з найбільш популярних сучасних різновидів командної оболонки UNIX. Особливо популярна в середовищі Linux, де вона часто використовується в якості передвстановленою командної оболонки.

Bash - це командний процесор, що працює, як правило, в інтерактивному режимі в текстовому вікні. Bash також може читати команди з файлу, який називається скриптом (або сценарієм). Як і всі Unix-оболонки, він підтримує автодоповнення назв файлів і тек, підстановку виведення результату команд, змінні, контроль за порядком виконання, оператори розгалуження і циклу. Ключові слова, синтаксис та інші основні особливості мови були запозичені з sh. Інші функції, наприклад, історія, були скопійовані з csh і ksh. Bash в основному задовольняє стандарту POSIX, але з низкою розширень [1].

Назва "bash" є акронімом від Bourne-again-shell ("ще-одна-командна-оболонка-Борна") і являє собою гру слів: Bourne-shell - одна з популярних різновидів командної оболонки для UNIX (sh), автором якої є Стівен Борн ( 1978), вдосконалена в 1987 Брайаном Фоксом. Прізвище Bourne (Борн) перегукується з англійським словом born, що означає "народжений", звідси: народжена-знов-командна оболонка.


1. Відмінності в синтаксисі

Переважна більшість важливих скриптів командного процесора Bourne можуть виконуватися без зміни в bash, за винятком тих, які посилаються на спеціальні змінні Bourne або використовують вбудовані команди Bourne. Синтаксис команд Bash включає ідеї, запозичені у Korn shell ( ksh) та C shell ( csh), такі як редагування командного рядка, історія команд, стек каталогів, змінні $RANDOM і $PPID, синтаксис заміни команди $(). Коли Bash використовується як інтерактивний командний процесор, він підтримує автозавершення імен програм, файлів, змінних і т. п. за допомогою клавіші Tab ⇆.


2. Внутрішні команди

Ввід / вивід
echo виводить вираз або вміст змінної (на stdout)
printf команда форматованого виведення, розширений варіант команди echo
read "Читає" значення змінної зі стандартного вводу (stdin), в інтерактивному режимі це клавіатура
Файлова система
cd змінює поточний каталог
pwd виводить назву поточного робочого каталогу (від англ. print working directory )
Дії над змінними
let виробляє арифметичні операції над змінними
eval транслює список аргументів зі списку в команди
set змінює значення внутрішніх змінних скрипта
unset видаляє змінну (фактично встановлює її значення в null)
export експортує змінну, роблячи її доступною дочірнім процесам
declare, typeset задають і / або накладають обмеження на змінні
getopts використовується для розбору аргументів, переданих скрипту з командного рядка
Управління сценарієм
source, . (точка) запуск зазначеного сценарію
exit безумовне завершення роботи сценарію
exec замінює поточний процес новим, запускаються командою exec
shopt дозволяє змінювати ключі (опції) оболонки на льоту
Команди
true повертає код завершення нуль (успішне завершення)
false повертає код завершення, який свідчить про невдачу
type prog виводить повний шлях до prog
hash prog запам'ятовує шлях до prog
help COMMAND виводить коротку довідку по використанню внутрішньої команди COMMAND

3. Скрипти

У найпростішому випадку, скрипт - простий список команд, записаний у файл. Командний процесор повинен знати, що він повинен цей файл обробити, а не просто прочитати його вміст. Для цього служить спеціальна конструкція, звана shebang (англ.): #!. Символ # задає коментар, але в даному случає shebang означає, що після цього спецсимволи знаходиться шлях до інтерпретатора для виконання сценарію.

3.1. Синтаксис

Синтаксис команд bash - це розширений синтаксис команд Bourne shell. Остаточна специфікація синтаксису команд Bash є в Bash Reference Manual, поширюваному проектом GNU. [2]

3.1.1. "Hello world"

 #! / Usr / bin / env bash  echo  "Hello World!" 

Цей скрипт містить тільки два рядки. Перший повідомляє системі про те, яка програма використовується для запуску файлу. Другий рядок - це єдина дія, яка виконується цим скриптом, він власне друкує 'Hello world!' в терміналі.

3.2. Запуск скрипта

Для того, щоб скрипт став виконуваним, можуть бути використані наступні команди:

 chmod  + Rx scriptname  # Видача прав на читання / виконання будь-якому користувачеві  chmod  u + rx scriptname  # Видача прав на читання / виконання тільки "власнику" скрипта 

З міркувань безпеки, шлях до поточного каталогу " . " не включений в змінну оточення $PATH. Тому для запуску скрипта необхідно явно вказувати шлях до поточного каталогу, в якому знаходиться скрипт:

 .  /  scriptname 

3.3. Перенаправлення вводу-виводу

В bash є вбудовані файлові дескриптори: 0 (stdin), 1 (stdout), 2 (stderr).

  • stdout - стандартний вивід програми.
  • stdin - стандартний ввід. Те, що набирає користувач в консолі.
  • stderr - стандартний вивід помилок.

Для операцій з цими дескрипторами, існують спеціальні символи: > (перенаправлення виводу), < (перенаправлення вводу). Символ & означає покажчик на дескриптор 1 (stdout).

1>filename Перенаправлення виводу у файл "filename", файл перезаписується вступниками даними
1>>filename Перенаправлення виводу у файл "filename", дані додаються в кінець файлу
2>filename Перенаправлення стандартного виводу помилок у файл "filename"
2>>filename Перенаправлення стандартного виводу помилок у файл "filename", дані додаються в кінець файлу
&>filename Перенаправлення виводу і помилок в файл "filename"
2>&1 Перенаправлення виводу помилок на стандартний вивід

Bash має індивідуальний синтаксис перенаправлення, який не підтримується в Bourne shell. Приклад одночасного перенаправлення стандартного виводу і стандартних помилок:

 command  &>  file 

це простіше набрати, ніж еквівалентну команду в синтаксисі Bourne shell

 command  >  file  2  > &  1 

Підтримується heredoc-синтаксис :

 command  << MYDOC123 багаторядковий текст MYDOC123 

Починаючи з версії 2.05b, bash може перенаправляти стандартний ввід з рядка, використовуючи наступний синтаксис " here strings ":

 command  <<<  "String to be read as standard input" 

Якщо рядок містить пробіли, її слід взяти в лапки.

Приклад (перенаправлення стандартного виводу у файл, запис даних, закриття файлу, скидання stdout):

 # Make Filedescriptor (FD) 6 a copy of stdout (FD 1)  exec  6  > &  1  # Open file "test.data" for writing  exec  1  >  test.data  # Produce some content  echo  "Data: data: data"  # Close file "test.data"  exec  1  > &  -  # Make stdout a copy of FD 6 (reset stdout)  exec  1  > &  6  # Close FD6  exec  6  > &  - 

Відкриття та закриття файлів:

 # Open file test.data for reading  exec  6  <  test.data  # Read until end of file  while  read  -U  6  dta  do  echo  "  $ Dta  "  done  # Close file test.data  exec  6  <&  - 

Захоплення виведення зовнішніх команд:

 # Виконати 'find' і помістити результат в VAR  # Пошук файлів, які закінчуються на "h"  VAR  = $  (  find  .  -Name  "* H"  ) 

3.4. Умовний оператор

 #! / Usr / bin / env bash  T1  =  "Foo"  T2  =  "Bar"  if  [  "  $ T1  "  =  "  $ T2  "  ]  ;  then  echo  умова виконується  else  echo  умова не виконується  fi 

3.5. Цикли

 #! / Usr / bin / env bash  for  i  in  `  seq  1  10  `  ;  do  echo  $ I  done 
 #! / Usr / bin / env bash  COUNTER  =  0  while  [  $ COUNTER  -Lt  10  ]  ;  do  echo  The counter is  $ COUNTER  let  COUNTER  = COUNTER +  1  done 
 #! / Usr / bin / env bash  i  =  0  until  [  $ I  -Eq  10  ]  do  echo  $ I  i  = $  [  $ I  +  1  ]  done 

3.6. Масиви

3.6.1. Індексовані масиви

Bash має підтримку одновимірних масивів. Ініціалізувати елементи масиву можна у вигляді: my_array[xx]. Також можна явно оголосити масив в сценарії, за допомогою директиви declare :

 declare  -A  my_array 

Звертатися до окремих елементів масиву можна за допомогою фігурних дужок, тобто: ${my_array[xx]}.

Ініціалізувати індексований масив можна двома способами:

1)

 Array  =  (  element1 element2 element3  ) 

2)

 temp_array  [  0  ]  = Element1 temp_array  [  5  ]  = Element temp_array  [  9  ]  = ElementN 

Додавання елементів в кінець індексованого масиву:

 declare  -A  arrAnimals  arrAnimals  =  (  dog elephant horse cow  )  # Виводимо вміст масиву:  echo  $ {ArrAnimals [@]}  # В кінець масиву arrAnimals додаємо новий елемент: "pig"  arrAnimals + =  (  pig  )  # І знову показуємо вміст масиву:  echo  $ {ArrAnimals [@]} 

3.6.2. Асоціативні масиви

Починаючи з версії 4.0 в Bash з'явилася підтримка асоціативних масивів (так званих hash-масивів).

Для оголошення асоціативних масивів використовується ключ-A вбудованої команди declare:

 declare  -A  hshArray 

Як і у випадку з індексованими масивами, для заповнення асоціативних масивів можуть використовуватися два різних синтаксису:

1)

 TheCapitalOf  [  Georgia  ]  =  'Tbilisi'  TheCapitalOf  [  Australia  ]  =  'Canberra'  TheCapitalOf  [  Pakistan  ]  =  'Islamabad' 

2)

 TheCapitalOf  =  (  [  Georgia  ]  =  'Tbilisi'  [  Australia  ]  =  'Canberra'  [  Pakistan  ]  =  'Islamabad'  ) 


За допомогою асоціативних масивів можна імітувати підтримку багатовимірних масивів:

 declare  -A  a  # Оголошує асоціативний масив 'a'  i  =  1  ;  j  =  2  # Ініціалізація декількох індексів  a  [  $ I  ,  $ J  ]  =  5  # Присвоєння значення "5" в клітинку "$ i, $ j" (тобто "1,2")  echo  $ {A [$ i, $ j]}  # Висновок збережених значень з "$ i, $ j" 

На жаль, в поточних версіях BASH Cкопіровать вміст одне асоціативного масиву в інший простим присвоюванням неможливо. Дану проблему можна тільки обійти, для чого існують два принципово різних підходи: Можна

  • Емулювати декларацію другий хешу "з нуля" шляхом копіювання декларація першого хешу:
 declare  -A  hsh1  hsh1  =  (  ...  )  eval  $  (  declare  -P  hsh1  |  sed  'S / declare-A hsh1/declare-A hsh2 /'  ) 
  • Перебрати всі елементи хеша-джерела і скопіювати їх в цільовій хеш:
 declare  -A  hsh1 hsh2  hsh1  =  (  ...  )  for  k  in  $ {! Hsh1 [@]}  ;  do  hsh2  [  $ K  ]  =  $ {Hsh1 [$ k]}  done 

3.7. Конвеєр

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

Приклад (grep працює як фільтр для стандартного виводу):

 cat  filename  |  grep  something 

3.8. Логічні змінні

|| логічна операція OR (логічне АБО). В операціях перевірки умов, оператор | | повертає 0 (success), якщо один з операндів має значення true (ІСТИНА).

&& логічна операція AND (логічне І). В операціях перевірки умов, оператор && повертає 0 (success) тоді, і тільки тоді, коли обидва операнди мають значення true (ІСТИНА).

3.9. Цілочисельна математика

Головне обмеження Bourne shell це те, що він не може виконувати обчислення з цілими числами без створення зовнішнього процесу. Bash може виконувати цілочисельні обчислення всередині процесу використовуючи команду (()) і синтаксис змінної $[], як показано нижче:

 VAR  =  55  # Встановлюємо змінну VAR, рівної 55  (  (  VAR = VAR +  1  )  )  # Додаємо одиницю до змінної VAR. Зверніть увагу на відсутність знака '$'  (  (  + + VAR  )  )  # Інший спосіб збільшення VAR на одиницю. Виконує префіксний інкремент  (  (  VAR + +  )  )  # Інший спосіб збільшення VAR на одиницю. Виконує постфіксной інкремент  echo  $  [  VAR  *  22  ]  # Множимо VAR на 22 і передаємо результат команді  echo  $  (  (  VAR  *  22  )  )  # Інший спосіб зробити те ж 

Команда (()) так само може використовуватися в умовних твердженнях, так як її вихідний параметр це 0 або 1, які можуть інтерпретуватися як true або false:

 if  (  (  VAR == Y  *  3  + X  *  2  )  )  then  echo  Yes  fi  (  (  Z  >  23  )  )  &&  echo  Yes 

Команда (()) підтримує наступні відносні оператори: == != > < >= <=.

Bash не підтримує обчислення всередині процесу з числами з плаваючою точкою. Тільки командні процесори UNIX Korn-shell (версія 1993) та zsh (починаючи з версії 4.0) підтримують цю можливість.

Список математичних операцій: +, -, *, /, ** (зведення в ступінь), % (розподіл по модулю, залишок від ділення), let - дозволяє використовувати скорочення арифметичних команд (скорочуючи кількість використовуваних змінних; наприклад: a += b еквівалентно a = a+b і т. п.).


4. Змінні та аргументи

Аргументи:

$$ pid поточного shell (самого процесу-сценарію)
$! pid останнього процесу у фоновому режимі
$? код повернення останнього процесу (функції або скрипта)
$ x де x - номер параметра, переданого скрипту ( $1, $2 і т. д., $0 - останній запущений скрипт)
$# кількість аргументів командного рядка
$* всі аргументи у вигляді одного рядка (слова)
$@ те ж саме, що і $*, але при цьому кожен параметр представлений як окремий рядок (слово)
$- список прапорів, переданих сценарієм
$_ містить останній аргумент попередньої команди

Вбудовані змінні:

$BASH шлях до виконуваного файлу bash
$BASH_VERSINFO[n] масив, що складається з 6 елементів, що містить інформацію про версії bash
$BASH_VERSION версія Bash, встановленого в системі
$DIRSTACK вміст вершини стека каталогів
$EDITOR заданий за замовчуванням редактор
$EUID "Ефективний" ідентифікаційний номер користувача (Effective User ID)
$FUNCNAME ім'я поточної функції
$GLOBIGNORE перелік шаблонних символів, які будуть проігноровані при виконанні підстановки імен файлів (globbing)
$GROUPS групи, до яких належить поточний користувач
$HOME домашній каталог користувача
$HOSTNAME мережеве ім'я хоста
$HOSTTYPE тип машини (ідентифікує апаратну архітектуру)
$IFS роздільник полів під введеної рядку
$LC_COLLATE задає порядок сортування символів, в операціях підстановки імен файлів і в пошуку за шаблоном
$LC_CTYPE визначає кодування символів
$LINENO Номер рядка виконуваного сценарію
$MACHTYPE апаратна архітектура
$OLDPWD колишній робочий каталог
$OSTYPE тип операційної системи
$PATH шлях пошуку (включає в себе каталоги / usr / bin /, / usr/X11R6/bin /, / usr / local / bin і т. д.)
$PIPESTATUS Код повернення каналу (конвеєра)
$PPID PID (ідентифікатор) батьківського процесу
$PS1 запрошення командного рядка
$PS2 вторинне запрошення командного рядка, виводиться тоді, коли від користувача очікується додатковий введення. Відображається як ">"
$PS3 третинне запрошення, виводиться, коли користувач повинен зробити вибір в операторі select
$PS4 запрошення четвертого рівня, виводиться на початку кожного рядка виводу тоді, коли сценарій викликається із ключем -x. Відображається як "+"
$PWD робочий (поточний) каталог
$REPLY змінна за замовчуванням, куди записується введення користувача, виконаний за допомогою команди read
$SECONDS час роботи сценарію (в секундах)
$SHELLOPTS список допустимих опцій інтерпретатора (доступна тільки для читання)
$SHLVL рівень вкладеності shell

4.1. Регулярні вирази всередині процесу

Bash 3.0 підтримує вбудовані регулярні вирази, з синтаксисом подібним синтаксису Perl :

 [  [  string = ~ regex  ]  ] 

Синтаксис регулярних виразів задокументований на сторінках документації man 7 regex. Статус виходу встановлюється в 0, якщо регулярний вираз співпало з рядком, і 1, якщо ні. Значення подвираженія, укладеного в дужки, можна отримати через змінну $ {BASH_REMATCH [@]}, наприклад:

 REGEXP  =  'Foo (bar) bl (. *)'  if  [  [  "Abcfoobarbletch"  = ~  $ REGEXP  ]  ]  then  echo  "Регулярний вираз співпало з рядком!"  echo  "  $ BASH_REMATCH  "  # Виводить: foobarbletch  echo  "  $ {BASH_REMATCH [1]}  "  # Виводить: bar  echo  "  $ {BASH_REMATCH [2]}  "  # Виводить: etch  fi 

Вбудовані регулярні вирази працюють швидше, ніж виконання зовнішньої команди grep, тому що відповідне регулярний вираз виконується в рамках процесу Bash. Якщо регулярний вираз чи рядок містять пробіли або метасимволи (такі як * або?), Їх слід взяти в лапки. Рекомендується використовувати змінну для зберігання регулярного виразу, як у вищенаведеному прикладі, для уникнення проблем з екрануванням спеціальних символів. Можна використовувати висновок bash з опцією -x для перевірки, як саме bash сприймає ваше регулярний вираз.


5. Розширення дужок

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

 # Це особливість притаманна bash  echo  a  {  p, c, d, b  }  e  # Ape ace ade abe 

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

 # Традиційна оболонка не дає той же результат  echo  a  {  p, c, d, b  }  e  # A {p, c, d, b} e 

Коли використовується розширення дужок у поєднанні з символами підстановки, дужки розкриваються першими, а потім результат обробляється в звичайному режимі. Таким чином, список JPEG і PNG зображень в поточному каталозі може бути отриманий так:

 ls  *  .  {  jpg, jpeg, png  }  # Дужки розкриваються до *. Jpg *. Jpeg *. Png - після чого виконується регулярний вираз 

6. Гарячі клавіші

  • Tab ⇆: Автодоповнення рядки за курсором.
  • Ctrl + a: Переміщає курсор в початок рядка (еквівалентно клавіші Home).
  • Ctrl + b: Переміщає курсор на один символ назад.
  • Ctrl + c: Посилає сигнал SIGINT поточному завданню, який зазвичай (але не завжди) припиняє і закриває його.
  • Ctrl + d: Посилає маркер EOF, який (якщо не відключено опцією і поточна рядок не містить тексту) закриває поточну оболонку (еквівалентно команді exit).
  • Ctrl + d: Видаляє поточний символ (Тільки якщо є текст на поточному рядку).
  • Ctrl + e: Переміщає курсор в кінець рядка (еквівалентно клавіші End).
  • Ctrl + f: Переміщає курсор на один символ вперед.
  • Ctrl + h: Видаляє попередній символ (те ж саме, що і клавіша Backspace).
  • Ctrl + i Еквівалентно клавіші Tab.
  • Ctrl + j Еквівалентно клавіші Enter.
  • Ctrl + k Очищає вміст рядка після курсору і копіює це в буфер обміну.
  • Ctrl + l Очищає вміст екрану (еквівалентно команді clear).
  • Ctrl + n (наступне) викликає наступну команду (еквівалентно клавіші ↓).
  • Ctrl + o Виконує знайдену команду в історії, і вибирає наступний рядок щодо поточного рядка в історії для того, щоб відредагувати.
  • Ctrl + p (попереднє) викликає попередню команду (еквівалентно клавіші ↑).
  • Ctrl + u: Очищає зміст рядка до курсору і копіює його в буфер обміну.
  • Ctrl + w: Прибирає слово до курсору і копіює його в буфер обміну.
  • Ctrl + y: додає вміст буфера обміну від позиції курсора.
  • Ctrl + z: Посилає сигнал SIGTSTP поточному завданню, який призупиняє його виконання. Для поновлення його виконання у фоновому режимі можна ввести команду bg. Для того, щоб повернути його з фонового режиму або призупинення можна виконати fg.
  • Alt + b: (назад) переміщує курсор назад на одне слово.
  • Alt + d: Скорочує слово після курсору.
  • Alt + f: (вперед) переміщує курсор вперед на одне слово.
  • Ctrl + x Ctrl + e: Редагує поточний рядок в програмі $ EDITOR, або vi якщо не визначено.
  • Ctrl + x Ctrl + v Виведення на екран інформації про версії поточного екземпляра bash.

7. Стартові скрипти

Bash при запуску викликає команди з безлічі різних скриптів.

Коли Bash викликається як інтерактивна оболонка входу в систему, першою справою він читає і викликає команди з файлу / etc / profile, якщо цей файл існує. Після читання цього файлу, він дивиться наступні файли в наступному порядку: ~ /. Bash_profile, ~ /. Bash_login і ~ /. Profile, читає і викликає команди з першого, який існує і доступний для читання. При виході bash читає і виконує команди з файлу ~ /. Bash_logout.

Коли запускається інтерактивна оболонка, але не для входу в систему, bash читає і виконує команди з файлів / etc / bash.bashrc і ~ /. Bashrc, якщо вони існують. Це може бути скасоване опцією -norc. Опція -rcfile file змусить Bash використовувати команди з файлу file замість / etc / bash.bashrc і ~ /. bashrc.


8. Переносимість

Скрипти оболонок, написані зі специфічними для bash особливостями (bashism-и) не будуть працювати на системах, де використовується Bourne shell або один з його замінників, без того, щоб bash був встановлений як додаткова оболонка, і, звичайно, скрипти треба починати з #!/bin/bash. Ця проблема стала особливо важливою, коли Ubuntu почав з жовтня 2006 року поставляти Debian Almquist shell (dash) як скриптова оболонку за замовчуванням, що призвело до непрацездатності численних скриптів.


Примітки

  1. Bill McCarty, Learning Debian GNU / Linux / Conquering the BASH Shell - oreilly.com/openbook/debian/book/ch13_01.html
  2. Bash Reference Manual - www.gnu.org / software / bash / manual / bashref.html