7575

9 занимательных вещей о shell, о которых вы могли не знать

Очень сложно представить работу админа без использования терминала и командной оболочки. Сегодня мы поговорим о shell и тонкостях работы с ним.

Давайте же узнаем, какие занимательные вещи хранит в себе Bourne again shell.

Bash – это не только командный процессор, а еще и полноценный язык программирования, используемый для автоматизации рутинных процессов и кодинга. В сети можно найти массу материалов с информацией разного уровня сложности. В этой статье мы собрали 9 фактов, которые могут облегчить вашу жизнь и сделать простое еще проще.

1) '' vs $()

Эти два оператора выполняют одно и то же. Сравните 2 строки:

$ echo `ls`
$ echo $(ls)

Если вы не знаете, обе формы заменяют вывод команды, содержащейся в них командой. Главное отличие в том, что вложение проще.

Какая из этих строк проще читается (и пишется)?

$ echo `echo \`echo \\\`echo inside\\\`\``

или:

$ echo $(echo $(echo $(echo inside)))

2) Подстановка vs regexps

Очень коварная штука, которая не всегда понятна с первого раза. Хотя подстановка и регулярное выражение может выглядеть одинаково, они будут выполнять разные действия. Посмотрим на строку:

$ rename -n 's/(.*)/new$1/' *

Две звездочки интерпретируются по-разному.

Первая звездочка игнорируется оболочкой (потому что она в кавычках) и интерпретируется как «0 или более символов». Таким образом, это распознаётся как регулярное выражение.

Вторая – трактуется shell-ом (потому что она не входит в кавычки), и заменяется списком всех файлов в текущей рабочей папке. Интерпретируется как подстановка.

Если обратиться к man bash , вы сможете понять, почему эти две команды выдают разные результаты?

$ ls *
$ ls .*

Второе выражение больше похоже на регулярное выражение, но это не так.

3) Коды выхода

Не все знают, что каждый раз, когда вы запускаете команду в shell, в оболочку возвращается «код выхода».

Как правило, если команда успешно выполняется, вы получаете код 0, иначе – ненулевое значение. Единица является «общей ошибкой», а другие могут дать вам дополнительную информацию (например, какой сигнал убил ее).

Но эти правила не всегда выполняются:

$ grep not_there /dev/null
$ echo $?

$? – специальная переменная bash, которой назначается код завершения каждой команды после ее запуска. Grep использует код выхода, чтобы показать, нашлось что-то или нет.

4) Условные операторы, [ и [[

Вот еще один кусок кода, который похож на предыдущий пример:

if grep not_there /dev/null
then
    echo hi
else
    echo lo
fi

Вместо кода выхода grep возвращает значение из кода.

Что выведет код:

  • hihi
  • lolo
  • something else
if [ $(grep not_there /dev/null) = '' ]
then
    echo -n hi
else
    echo -n lo
fi
if [[ $(grep not_there /dev/null) = '' ]]
then
    echo -n hi
else
    echo -n lo
fi

В первом блоке if не имеет смысла потому, что $(grep not_there /dev/null) – это пустота, которая приводит к такому сравнению:

[ = '' ]

Иногда можно встретить странное сравнение:

if [ x$(grep not_there /dev/null) = 'x' ]

оно ничего не возвращает, но продолжает работать.

5) set s

У Bash есть настраиваемые параметры, которые можно установить «на лету». Довольно часто используются два из них:

set -e

выход из сценария, если какая-либо команда вернула ненулевой код.

Это выводит команды, которые запускаются при запуске скрипта:

set -x

Таким образом, сценарий может начинаться так:

#!/bin/bash
set -e
set -x
grep not_there /dev/null
echo $?

Что выведет код?

6) ​​< ( )

Данный приём мало где используется, возможно, потому, что это может сильно озадачить пользователя.

Схожесть с $() заключается в том, что вывод команды внутри повторно используется. В этом случае вывод обрабатывается как файл и может быть использован в команде, которая принимает такие аргументы.

Вы делали когда-нибудь подобное?

$ grep somestring file1 > /tmp/a
$ grep somestring file2 > /tmp/b
$ diff /tmp/a /tmp/b

Это сработает, но можно было написать так:

diff <(grep somestring file1) <(grep somestring file2)

7) Кавычки

Кавычки – ключевой объект в bash, как и во многих контекстах программного обеспечения.

Во-первых, переменные в кавычках:

A='123'  
echo "$A"
echo '$A'

Довольно просто – двойные кавычки разыменовывают переменные, а одинарные кавычки приводят к литералу.

Какой вывод будет здесь?

mkdir -p tmp
cd tmp
touch a
echo "*"
echo '*'

8) Полезные указатели

В man bash есть масса примеров указателей, которые значительно облегчают жизнь. Здесь мы рассмотрим три распространенных указателя, а наиболее очевидные (например, !! – повторить последнюю команду и ~ – домашний каталог) опустим.

!$ – повторяет последний аргумент последней команды. Если вы работаете с файлом, то можете не тратить время на ввод дублирующей строки:

grep somestring /long/path/to/some/file/or/other.txt
vi !$

!:1-$ берет все аргументы предыдущей команды и запоминает.

grep isthere /long/path/to/some/file/or/other.txt
egrep !:1-$
fgrep !:1-$

! означает «смотреть на предыдущую команду», : – разделитель, 1 означает «взять первое слово»,  означает «до», $ – последнее слово.

Похожего результата можно добиться при помощи !*. Этот указатель дает возможность ограничить определенное непрерывное подмножество аргументов, например, с помощью !:2-3.

:h – если поместить данную команду после имени файла, он изменит имя файла, чтобы удалить все до папки.

grep isthere /long/path/to/some/file/or/other.txt
cd !$:h

9) Порядок загрузки

Запоминание порядка, в котором shell запускает сценарии, может вызвать бурю эмоций. Вот вам диаграмма того, что происходит у shell «в голове»:

Порядок запуска shell

Она показывает, как shell решает запускать скрипт  в зависимости от контекста, в котором он запущен (цветами указаны принимаемые решения).

Поэтому если вы находитесь в локальной (не ssh), nologin, интерактивной оболочке (например, когда запускаете shell из командной строки), это зеленая линия:

/etc/bash.bashrc
~/.bashrc
[bash runs, then terminates]
~/.bash_logout

Bash – очень занятная оболочка, которая имеет большой потенциал и приносит огромную пользу в ежедневной рутине. Рассмотренные примеры команд облегчат работу в командной строке *nix системы. Не останавливайтесь на этих трюках, исследуйте дальше бескрайние просторы bash и будьте аккуратны с rm -rf /.

Оригинал

Другие материалы по теме:

РУБРИКИ В СТАТЬЕ

Комментарии

BUG
LIVE