Перейти до змісту

Bash - введення даних і маніпуляції

У цьому розділі ви дізнаєтесь, як змусити ваші сценарії взаємодіяти з користувачами та маніпулювати даними.


Цілі: В цьому розділі ви дізнаєтеся як:

✔ прочитати введені дані від користувача;
✔ маніпулювати записами даних;
✔ використовувати аргументи в сценарії;
✔ керувати позиційними змінними;

🏁 linux, сценарій, bash, змінна

Знання: ⭐ ⭐
Складність: ⭐ ⭐

Час для читання: 10 хвилин


Залежно від мети сценарію, йому може знадобитися інформація під час запуску або під час виконання. Ця інформація, не визначена під час написання сценарію, може надходити з файлів або введених користувачем даних або передаватися як аргументи під час введення команди сценарію, подібно до багатьох команд Linux.

Команда read

Команда read дозволяє ввести рядок символів і зберегти його в змінній.

Синтаксис команди read:

read [-n X] [-p] [-s] [variable]

У першому прикладі нижче пропонується ввести дві змінні: «name» та «firstname», але оскільки підказки немає, вам слід знати заздалегідь, що це так. У випадку цього конкретного запису кожна вхідна змінна буде розділена пробілом. У другому прикладі пропонується ввести змінну "name" з текстом підказки:

read name firstname
read -p "Please type your name: " name
Опція Функціональність
-p Відображає підказку.
-n Обмежує кількість символів, які потрібно ввести.
-s Приховує введення.

Якщо використовується параметр -n, оболонка автоматично перевіряє введені дані після вказаної кількості символів. Користувачеві не потрібно натискати клавішу Enter.

read -n5 name

Команда read дозволяє перервати виконання сценарію, поки користувач вводить інформацію. Введені користувачем дані розбиваються на слова, призначені одній або кільком попередньо визначеним змінним. Слова — це рядки символів, розділені роздільником полів.

Кінець введення визначається натисканням клавіші Enter.

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

Поділ слів визначається символом роздільника полів. Цей роздільник зберігається в системній змінній IFS (Internal Field Separator).

set | grep IFS
IFS=$' \t\n'

За замовчуванням IFS містить пробіл, вкладку та переклад рядка.

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

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

echo -n "Press [ENTER] to continue..."
read

Команда cut

Команда cut дозволяє виділити стовпець у файлі або потоці.

Синтаксис команди cut:

cut [-cx] [-dy] [-fz] file

Приклад використання команди cut:

cut -d: -f1 /etc/passwd
Опція Функціональність
-c Визначає порядкові номери символів, які потрібно вибрати.
-d Визначає роздільник полів.
-f Вказує порядковий номер стовпців для вибору.

Основною перевагою цієї команди буде її асоціація з потоком, наприклад, команда grep і канал |.

  • Команда grep працює "по вертикалі" (ізоляція одного рядка від усіх рядків у файлі).
  • Комбінація двох команд дозволяє ізолювати конкретне поле у файлі.

Приклад:

grep "^root:" /etc/passwd | cut -d: -f3
0

Важливо

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

Команда tr

Команда tr дозволяє конвертувати рядок.

Синтаксис команди tr:

tr [-csd] string1 string2
Опція Функціональність
-c Усі символи, не вказані в першому рядку, перетворюються на символи другого рядка.
-d Видаляє вказаний символ.
-s Зменшує вказаний символ до однієї одиниці.

Нижче наведено приклад використання команди tr. Якщо ви використовуєте grep, щоб повернути запис у файлі root passwd, ви отримаєте наступне:

grep root /etc/passwd

повертає:

root:x:0:0:root:/root:/bin/bash

Тепер давайте скористаємося командою tr і зменшимо «о» в рядку:

grep root /etc/passwd | tr -s "o"

яка повертає наступне:

rot:x:0:0:rot:/rot:/bin/bash

Витягнути назву та шлях до файлу

Команда basename дозволяє отримати назву файлу зі шляху.

Команда dirname дозволяє витягнути батьківський шлях до файлу.

Приклади:

echo $FILE=/usr/bin/passwd
basename $FILE

Що призведе до "passwd"

dirname $FILE

Що призведе до: "/usr/bin"

Аргументи сценарію

Запит на введення інформації за допомогою команди read перериває виконання сценарію, доки користувач не введе будь-яку інформацію.

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

Багато команд Linux працюють за цим принципом.

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

Його основним недоліком є те, що користувача потрібно буде попередити про синтаксис сценарію, щоб уникнути помилок.

Аргументи заповнюються під час введення команди сценарію. Вони розділені пробілом.

./script argument1 argument2

Після виконання сценарій зберігає введені аргументи у попередньо визначених змінних: позиційних змінних (positional variables).

Ці змінні можна використовувати в сценарії, як і будь-яку іншу змінну, за винятком того, що їх не можна призначати.

  • Невикористані позиційні змінні існують, але вони порожні.
  • Позиційні змінні завжди визначаються однаково:
Змінна Функціональність
$0 містить введену назву сценарію.
$1 to $9 містить значення аргументів з 1 по 9
${x} містить значення аргументу x, більше 9.
$# містить кількість переданих аргументів.
$* або $@ містить в одній змінній усі передані аргументи.

Приклад:

#!/usr/bin/env bash
#
# Author : Damien dit LeDub
# Date : september 2019
# Version 1.0.0 : Display the value of the positional arguments
# From 1 to 3

# The field separator will be "," or space
# Important to see the difference in $* and $@
IFS=", "

# Display a text on the screen:
echo "The number of arguments (\$#) = $#"
echo "The name of the script  (\$0) = $0"
echo "The 1st argument        (\$1) = $1"
echo "The 2nd argument        (\$2) = $2"
echo "The 3rd argument        (\$3) = $3"
echo "All separated by IFS    (\$*) = $*"
echo "All without separation  (\$@) = $@"

Це дасть:

$ ./arguments.sh one two "tree four"
The number of arguments ($#) = 3
The name of the script  ($0) = ./arguments.sh
The 1st argument        ($1) = one
The 2nd argument        ($2) = two
The 3rd argument        ($3) = tree four
All separated by IFS    ($*) = one,two,tree four
All without separation  ($@) = one two tree four

Важливо

Зверніть увагу на різницю між $@ і $*. Це у форматі зберігання аргументів:

  • $*: містить аргументи у форматі "$1 $2 $3 ..."
  • $@ : містить аргументи у форматі "$1" "$2" "$3" ...

Різницю можна побачити лише шляхом зміни змінної середовища IFS.

Команда shift

Команда shift дозволяє зміщувати позиційні змінні.

Давайте змінимо наш попередній приклад, щоб проілюструвати вплив команди shift на позиційні змінні:

#!/usr/bin/env bash
#
# Author : Damien dit LeDub
# Date : september 2019
# Version 1.0.0 : Display the value of the positional arguments
# From 1 to 3

# The field separator will be "," or space
# Important to see the difference in $* and $@
IFS=", "

# Display a text on the screen:
echo "The number of arguments (\$#) = $#"
echo "The 1st argument        (\$1) = $1"
echo "The 2nd argument        (\$2) = $2"
echo "The 3rd argument        (\$3) = $3"
echo "All separated by IFS    (\$*) = $*"
echo "All without separation  (\$@) = $@"

shift 2
echo ""
echo "-------- SHIFT 2 ----------------"
echo ""

echo "The number of arguments (\$#) = $#"
echo "The 1st argument        (\$1) = $1"
echo "The 2nd argument        (\$2) = $2"
echo "The 3rd argument        (\$3) = $3"
echo "All separated by IFS    (\$*) = $*"
echo "All without separation  (\$@) = $@"

Це дасть:

./arguments.sh one two "tree four"
The number of arguments ($#) = 3
The 1st argument        ($1) = one
The 2nd argument        ($2) = two
The 3rd argument        ($3) = tree four
All separated by IFS    ($*) = one,two,tree four
All without separation  ($@) = one two tree four

-------- SHIFT 2 ----------------

The number of arguments ($#) = 1
The 1st argument        ($1) = tree four
The 2nd argument        ($2) =
The 3rd argument        ($3) =
All separated by IFS    ($*) = tree four
All without separation  ($@) = tree four

Як бачите, команда shift змістила місце аргументів «ліворуч», видаливши перші 2.

Попередження

Під час використання команди shift змінні $# і $* змінюються відповідно.

Команда set

Команда set розбиває рядок на позиційні змінні.

Синтаксис команди set:

set [value] [$variable]

Приклад:

$ set one two three
$ echo $1 $2 $3 $#
one two three 3
$ variable="four five six"
$ set $variable
$ echo $1 $2 $3 $#
four five six 3

Тепер ви можете використовувати позиційні змінні.

Author: Antoine Le Morvan

Contributors: Steven Spencer, Ganna Zhyrnova