Треки
/
Bash
Bash
/
Салабус
/
Команди та аргументи
Ко

Команди та аргументи у Bash

{one: "1 вправа", few: "%{count} вправи", many: "%{count} вправ", other: "%{count} вправи"}

Про концепцію Команди та аргументи

Оболонки

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

Існує багато різних оболонок командного рядка. Windows пропонує cmd і powershell. Mac і Linux пропонують «Unix-оболонки», яких є багато. Типова оболонка для Mac - zsh. csh - це застаріла оболонка із синтаксисом, схожим на C. bash - одна з найпопулярніших оболонок, особливо в Linux.

Однією з найперших оболонок є оболонка Bourne, sh. Згодом цю оболонку стандартизували, щоб вона була доступна в кожній Unix-подібній системі. Багато оболонок базуються на оболонці Bourne, часто надаючи додаткову інтерактивну чи програмну функціональність.

Bash базується на оболонці Bourne. Ось чому її називають «Bourne-again shell». Це типова оболонка в багатьох системах Linux. Bash має багато засобів, які роблять її зручною інтерактивною оболонкою, зокрема:

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

Цей трек не про те, як користуватися bash як інтерактивною оболонкою. Ідеться про те, щоб навчитися писати програми за допомогою bash. Наголос буде на використанні лише bash для розвʼязання задач, хоча немає жодних обмежень на виклик зовнішніх інструментів.

Основи Bash: команди та аргументи

Bash читає команди зі свого введення (зазвичай це термінал або файл). Кожен рядок введення, який вона читає, вважається командою, тобто вказівкою, яку потрібно виконати. (Є кілька складніших випадків, як-от команди, що займають кілька рядків; про них поговоримо пізніше.)

Bash розбиває кожен рядок на слова, розділені символами пробілів (пробіли й табуляції). Перше слово рядка - це назва команди, яку потрібно виконати. Усі інші слова стають аргументами цієї команди (опції, імена файлів тощо).

Note

У наведених нижче прикладах ми покажемо кілька інтерактивних команд, які можна запустити.

  • Символ # починає коментар. Усі слова після коментаря оболонка ігнорує; коментар призначений лише для читання.
  • Символ $ позначає запрошення оболонки. Якщо ми копіюємо команду, не включаймо запрошення.
# Note: It is always a good idea to run `ls` before `rm`
# to make sure you know what you are deleting.

$ rm *            # Remove all files in the current directory.
                  # Make sure you run this in a temp directory or you can lose files!
$ ls              # List files in the current directory (no output, no files).
$ touch a   b c   # Create files 'a', 'b' and 'c'.
$ ls              # List files again; this time the outputs: 'a', 'b' and 'c'.
a  b  c

rm - це програма, яка видаляє передані їй файли. * - це символ глобу, «шаблон підстановки», який збігається з усіма файлами в поточному каталозі. Про глоби поговоримо пізніше.

Чи помітили ми, що між a і b кілька пробілів, а між b і c лише один? Кількість пробілів між аргументами не має значення! Наприклад:

$ echo This is a test.
This is a test.
$ echo This    is    a    test.
This is a test.

echo - це команда, яка виводить свої аргументи у стандартний вивід (у нашому випадку це термінал). Bash розбиває команду на пʼять слів і викликає команду echo з чотирма аргументами. Зайві пробіли в другому прикладі нічого не змінюють. echo не знає, як саме пробіли стояли між словами спочатку.

Якщо ми хочемо зберегти зайві пробіли, треба передати речення як один-єдиний аргумент. Це можна зробити за допомогою лапок:

$ echo "This    is    a    test."
This    is    a    test.

Лапки групують усе всередині них в один аргумент. Аргументом є This is a test., включно з цими конкретними символами пробілів. Зауважмо, що лапки не є частиною аргументу: bash прибирає їх, перш ніж передати цей єдиний аргумент до echo.

Аргументи відокремлюються від назви команди та одне від одного пробілами. Це важливо запамʼятати. Наприклад, ось це неправильно:

$ [-f file]
bash: [-f: command not found

Ідеться про перевірку наявності файлу з назвою file. Здавалося б, можна припустити, що пробіли навколо [ і ] не мають значення, але [ насправді є командою, і вона вимагає, щоб її останній аргумент був ]. (Команду [ ми розглянемо докладніше пізніше.) Тому ми маємо відокремити [ від -f, а ] від file. Інакше bash вважатиме, що ми намагаємося виконати команду з назвою [-f з єдиним аргументом file]. Правильна команда відокремлює всі аргументи пробілами:

$ [ -f file ]

(Ми бачимо багато людей, яких ця поведінка бентежить; вони думають, що [...] - це «просто синтаксис», і пробіли можна опустити; але [ - це команда, і пробіли обовʼязкові.)

Якщо наше імʼя файлу містить пробіли чи інші спеціальні символи, його теж треба взяти в лапки:

$ [ -f "my file" ]

Типи команд

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

Типово псевдоніми ввімкнені лише в інтерактивних оболонках, а не в сценаріях оболонки. Тут ми їх розглядати не будемо.

Функції

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

Вбудовані команди

Bash має кілька базових вбудованих команд, як-от: cd (змінити каталог), echo (вивести дані) тощо. Їх можна вважати функціями, які вже надані.

Ключові слова

Ключові слова схожі на вбудовані команди, з тією головною відмінністю, що вони насправді є синтаксисом bash і можуть розбиратися за спеціальними правилами. Наприклад, [ - це вбудована команда bash, а [[ - ключове слово bash; обидва використовують для перевірки різних умов. Але ключове слово [[ має деяку додаткову функціональність. Наприклад, воно надає оператор =~, який виконує перевірку регулярним виразом.

$ [[ "hello world" =~ e.*o ]]   # returns a "success" status
$ [ "hello world" =~ e.*o ]
bash: [: =~: binary operator expected

Оператори порівняння рядків тексту (англ. string) < і > - ще один приклад того, як ключові слова по-різному розбирають код. Усередині [[...]] ці оператори не потребують особливої уваги.

$ if [[ "$USER" < "n" ]]; then
    echo "$USER is in the first half of the alphabet"
fi
# => glennj is in the first half of the alphabet

Але всередині [...] їх треба взяти в лапки або екранувати, щоб оболонка не розібрала їх як оператори перенаправлення.

$ if [ "$USER" < "n" ]; then
    echo "$USER is in the first half of the alphabet"
fi
# => bash: n: No such file or directory

$ if [ "$USER" \< "n" ]; then
    echo "$USER is in the first half of the alphabet"
fi
# => glennj is in the first half of the alphabet

Виконувані файли

Останній тип команд, які може виконувати bash, - це виконуваний файл. Це виконувані файли (програми) у файловій системі нашого компʼютера, які ми можемо запускати. (Виконувані файли також можуть називати зовнішніми командами або програмами.) Виконувані файли зазвичай викликають, вводячи лише їхню назву; повний шлях до файлу зазвичай не потрібен. Це можливо, бо bash використовує наперед визначену змінну, яка допомагає їй знаходити розташування типових виконуваних файлів. Ця змінна називається PATH. Це набір назв каталогів, розділених двокрапками (наприклад, /usr/bin:/bin). Коли команду вказують (наприклад, myprogram або ls) без шляху до файлу (і вона не є псевдонімом, функцією, вбудованою командою чи ключовим словом), bash переглядає каталоги зі змінної PATH. Каталоги переглядаються по черзі, зліва направо, щоб зʼясувати, чи містять вони виконуваний файл із заданою назвою.

Якщо виконуваний файл поза відомим шляхом, потрібно вказати шлях до цього файлу. Для виконуваного файлу myprogram у поточному каталозі використовуймо ./myprogram; якщо він у каталозі /opt/somedirectory, використовуймо /opt/somedirectory/myprogram.

Порада: команду type можна використати, щоб отримати подробиці про команду:

$ type rm
rm is hashed (/bin/rm)
# or it might return: `rm is /bin/rm`

$ type cd
cd is a shell builtin

Сценарії

Сценарій - це послідовність команд, збережена у файлі. Bash читає файл і обробляє команди по порядку. Вона переходить до наступної команди, лише коли завершилася поточна. Виняток - якщо команду вказано виконувати асинхронно (у фоновому режимі). Поки що не варто надто перейматися цим випадком; про те, як це працює, дізнаємося пізніше.

Будь-який приклад командного рядка з цього посібника можна також використати у сценарії.

Створити сценарій легко. Почнімо зі створення нового файлу й додаймо цей рядок першим:

#!/bin/bash

Цей рядок називається директивою інтерпретатора (її також називають hashbang або shebang). Він вказує, що /bin/bash слід використовувати як інтерпретатор, коли файл використовують як виконуваний у команді. Коли ядро операційної системи виконує небінарний файл, воно читає перший рядок файлу. Якщо рядок починається з #!, ядро використовує цей рядок, щоб визначити інтерпретатор, якому передати файл. (Є й інші слушні способи зробити це, див. нижче.) #! має бути на самому початку файлу, без пробілів чи порожніх рядків перед ним. Команди нашого сценарію стоятимуть на окремих рядках нижче.

Порада: замість #!/bin/bash можна використати

#!/usr/bin/env bash

env шукає у $PATH виконуваний файл, названий її першим аргументом (у цьому випадку «bash»). Докладніше про цю техніку та її відмінність від звичайного #!/bin/bash дивіться у цьому питанні на StackOverflow.

Не варто піддаватися на сценарії чи приклади з інтернету, які використовують /bin/sh як інтерпретатор. sh - це не bash! Сам Bash - це «sh-сумісна» оболонка: він може виконувати більшість сценаріїв sh і має багато того самого синтаксису. Однак навпаки це не так; деякі можливості bash зламаються або спричинять несподівану поведінку в sh. Насправді єдиної оболонки sh не існує. Існує багато реалізацій оболонки, які підтримують синтаксис POSIX-sh. Залежно від нашої операційної системи, коли ми запускаємо sh, ми насправді можемо виконувати bash, ash, dash чи якусь іншу оболонку.

Щойно файл сценарію створено, його можна виконати так:

$ bash myscript

У цьому прикладі ми виконуємо команду bash і кажемо їй прочитати сценарій, який ми передали як аргумент. Коли ми робимо це саме так, рядок #! - просто коментар.

Або ж ми можемо надати нашим сценаріям права на виконання. За такого способу ми можемо виконати сценарій як будь-який інший виконуваний файл, замість викликати bash вручну:

$ chmod +x myscript  # Mark the file as executable.
$ ./myscript         # Now, myscript can be executed directly
                     # instead of having to specify bash.

Коли ми запускаємо команду в такий спосіб, операційна система (ОС) використовує рядок #!, щоб визначити, який інтерпретатор застосувати для запуску нашого сценарію.

Джерела

Матеріал цього уроку взято з Commands and Arguments на Bash Guide.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці