Главная » Хабрахабр » Насколько хорошо ты знаешь bash?

Насколько хорошо ты знаешь bash?


Пользуешься командным интерпретатором каждый день? Готов решить несколько логических задачек и узнать что-то новое? Добро пожаловать под кат.
Часть представленных здесь задач не принесёт реальной пользы, так как затрагивает какие-то сложные граничные случаи. Другая же часть будет полезна тем, кто постоянно использует шелл и читает чужие скрипты.

4. Примечание: на момент написания статьи автор использовал bash 4. Сложность задач различная. 12(1)-release в подсистеме Linux на Windows 10.

Задача 1

$ cat 1
The cake is a lie!
$ cat 1 | head | tail | sed -e 's/alive/dead/g' | tee | wc -l > 1

Что будет выведено на экран?

Ответ

Ничего.

Объяснение

Таким образом файл 1 очищается перед запуском первой программы и cat открывает уже очищенный файл.
После интерпретации команды, но до запуска всех программ bash работает с указанными потоками ввода-вывода.

Задача 2

$ cat file1
I love UNIX!
$ cat file2
I don't like UNIX
$ cat file1 <file2

Что будет выведено на экран?

Ответ

I love UNIX!

Объяснение

Некоторые программы забивают на stdin, когда указаны файлы.

Задача 3

$ cat file
Just for fun
$ cat file 1>&2 2>/dev/null

Что будет выведено на экран?

Ответ

Just for fun

Объяснение

Есть заблуждение, что последовательность 1>&2 перенаправляет первый поток во второй, однако, это не так. Рассмотрим команду из задания. В начале интерпретации введённой команды таблица потоков выглядит так:

0

1

2

stdin

stdout

stderr

bash обнаруживает последовательность 1>&2 и копирует содержимое ячейки 2 в ячейку 1:

0

1

2

stdin

stderr

stderr

После обнаружения последовательности 2>/dev/null интерпретатор записывает значение в ячейку 2, оставляя другие ячейки нетронутыми:

0

1

2

stdin

stderr

/dev/null

bash выводит так же и поток ошибок, так что на мы обнаруживаем на экране текст файла.

Задача 4
Как вывод stdout отправить на stderr, а вывод stderr, наоборот, на stdout?

Ответ

4>&1 1>&2 2>&4

Объяснение

Именно поэтому нам требуется дополнительный поток для временного хранения.
Принцип ровно как и в предыдущей задаче.

Задача 5

Дан файл test.sh

#!/bin/bash
ls $*
ls $@
ls "$*"
ls "$@"

Выполняются команды:

$ ls
1 2 3 test.sh
$ ./test.sh 1 2 3

Что выведет скрипт?

Ответ

1 2 3
1 2 3
ls: cannot access '1 2 3': No such file or directory
1 2 3

Объяснение

В кавычках способ раскрытия меняется: $* превращается в "$1 $2 $3", а $@ в свою очередь в "$1" "$2" "$3". Без кавычек переменные $* и $@ ничем не отличаются и раскрываются во все заданные позиционные аргументы скрипта, разделённые пробелом. Так как файла «1 2 3» в каталоге нет, ls выводит ошибку

Задача 6

Создадим в текущей директории файл -c c правами 755 и таким содержимым:

#!/bin/bash echo $1

Обнулим переменную $PATH и попытаемся выполнить:

$ PATH=
$ -c "echo SURPRISE"

Что будет выведено на экран? Что произойдет, если повторить ввод последней команды?

Ответ

Первый раз будет выведено SURPRISE, второй раз echo SURPRISE

Объяснение

При пустом PATH шелл начинает искать файлы в текущем каталоге. -с как раз находится. Так как исполняемый файл — текстовый, считывается первая строчка на предмет шебанга. Команда собирется по шаблону:

<shebang> <filename> <args>

Таким образом, перед выполнением наша команда выглядит так:

/bin/bash -c "echo SURPRISE"

И, как следствие, выполняется совершенно не то, что мы хотели.

Единственный способ защититься от столь неожиданного эффекта — добавить два минуса в шебанг.
Если выполнить второй раз, то шелл подберёт информацию о -c из кэша и выполнит его уже верно.

Задача 7

$ ls file
$ cat <$(ls)
$ cat <(ls)

Что будет выведено на экран в первом и во втором случае?

Ответ

В первом будет выведено содержимое файла file, во втором — имя файла.

Объяснение

В первом случае выполняется подстановка

cat <file

Во втором случае <(ls) будет заменён на именованный пайп, соединённый входом с stdout ls, и выходом с stdin cat.

После подстановки команда приобретёт вид:

cat /dev/fd/xx

Задача 8

$ TEST=123456
$ echo $

Что будет выведено на экран?

Ответ

1234

Объяснение

При такой записи матчится паттерн (# — с начала переменной; ## — жадно с начала переменной; % — с конца переменной; %% — жадно с конца переменной) и удаляется при подстановке. Содержимое переменной при этом остаётся нетронутым. Таким образом, например, удобно получать имя файла без расширения.

$ TEST=file.ext
$ echo ${TEST%.ext}
file

Задача 9

$ echo ${friendship:-magic}

Что будет выведено на экран?

Ответ

Иначе — magic.
Если переменная friendship определена, то содержимое переменной.

Объяснение

В документации эта магия называется «unset or null» и позволяет использовать заданное дефолтное значение переменной в одну строчку.

Задача 10

while true; false; do echo Success
done

Что будет выведено на экран?

Ответ

Ничего

Объяснение

Так как там стоит false, цикл даже не начнётся.
Операторы while и if позволяют в условие запихать целую последовательность действий, однако результат (код возврата) будет учитываться только у последней команды.

Задача 11

$ false && true || true && false && echo 1 || echo 2

Что будет выведено на экран?

Ответ

2

Объяснение

Добавим скобочек для явного порядка и упростим команду, принимая во внимание, что учитывается только код возврата последней команды:

((((false && true) || true) && false) && echo 1) || echo 2
(((false || true) && false) && echo 1) || echo 2
((true && false) && echo 1) || echo 2
(false && echo 1) || echo 2
false || echo 2
echo 2

Замечания, пожелания и дополнительные задачи приветствуются в комментарии или ЛС.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Дайджест свежих материалов из мира фронтенда за последнюю неделю №335 (15 — 21 октября 2018)

Предлагаем вашему вниманию подборку с ссылками на новые материалы из области фронтенда и около него.     Медиа    |    Веб-разработка    |    CSS    |    Javascript    |    Браузеры    |    Занимательное Медиа • Подкаст «Веб-стандарты», Выпуск №142: Safari и Edge, бюджет на перфоманс, новые теги в HTML, киевское сообщество, кто такие Котаны?• Подкаст «Frontend Weekend» ...

Вышла Oracle Database 18c XE

Можно открывать шампанское и закатывать вечеринку — спустя более, чем 7 лет с момента выпуска предыдущего релиза, для скачивания наконец доступна свежайшая Oracle Database 18c XE. Свершилось! Пока только для Linux x64, но версии для других платформ, также как и ...