ZaLinux.ru

Операторы перенаправления вывода в Bash: что означает <<, <<<, < <(КОМАНДА), 2>&1 и другие

Рассмотрим операторы перенаправления вывода Bash и похожие по функции операторы и конструкции. Я собрал следующий список, если что-то пропустил, то пишите в комментариях:

|

Этот оператор на английском называется pipe, и на русском его называют труба или конвейер. Используется очень часто для перенаправления вывода из одной команды в другую, которая может принимать стандартный вывод. Например:

echo 'Строка с числом 901255323' | grep -E -o '[0-9]+'

Выведет:

901255323

>

Символ > используется для перенаправления вывода в файл, например:

ls -l > dir.txt

В этом примере вывод команды ls -l будет записан в файл dir.txt.

То есть оператор | используется когда вывод передаётся в другую команду, а оператор > используется когда вывод записывается в файл.

Ещё один пример использования сразу обоих операторов:

echo 'Строка с числом 901255323' | grep -E -o '[0-9]+' > num.txt

Результат работы этой последовательности команд будет сохранён в файл num.txt.

Если файл не существует, то он будет создан. Если файл существует, то оператор > полностью удалит его содержимое и запишет новым.

>>

Функция оператора >> похожа на > с тем отличием, что оператор >> не удаляет содержимое файла, а дописывает новые данные к уже существующим.

Если файл не существует, то оператор >> создаст его и запишет в него переданные данные.

2>

Оператор 2> перенаправляет стандартный вывод ошибок — standard error (stderr).

Результат выполнения команд и возникшие ошибки выводятся на консоль и может показаться, что это одно и то же. Но на самом деле, это разные типы вывода.

К примеру попытаемся сохранить в файл текст ошибки, возникшей в результате выполнения команды:

ls -l /bin/usr > ls-error.txt

Текст ошибки будет выведен на экран, но файл ls-error.txt окажется пустым.

Дело в том, что нужно различать стандартный вывод и стандартный вывод ошибок. Чтобы перенаправить стандартный вывод в файл используется оператор 2>:

ls -l /bin/usr 2> ls-error.txt

В данном случае ошибка не будет выведена на экран, а будет сохранена в файл ls-error.txt.

Чтобы перенаправить стандартную ошибку, мы должны обратиться к её файловому дескриптору. Программа может выводить любой из нескольких пронумерованных файловых потоков. Первые три из этих файловых потоков называются стандартный ввод, стандартный вывод и стандартный вывод ошибок. Оболочка ссылается на них внутренне как файловые дескрипторы 0, 1 и 2 соответственно. Оболочка обеспечивает запись для перенаправления файлов с использованием номера дескриптора файла. Поскольку стандартная ошибка совпадает с дескриптором файла номер 2, мы можем перенаправить стандартную ошибку с помощью 2>.

Файловый дескриптор «2» помещается непосредственно перед оператором перенаправления, чтобы выполнить перенаправление стандартной ошибки в файл ls-error.txt.

2>&1

Конструкция 2>&1 предназначена для перенаправления стандартного вывода и стандартного вывода ошибок в один файл.

В некоторых случаях мы можем захотеть записать весь вывод команды в один файл. Чтобы сделать это, мы должны одновременно перенаправить как стандартный вывод, так и стандартный вывод ошибок. Есть два способа сделать это. Во-первых, традиционный способ, который работает со старыми версиями оболочки:

ls -l /bin/usr > ls-output.txt 2>&1

Используя этот метод, мы выполняем два перенаправления. Сначала мы перенаправляем стандартный вывод в файл ls-output.txt, а затем перенаправляем дескриптор файла 2 (стандартная вывод ошибок) на дескриптор файла один (стандартный вывод), используя обозначения 2>&1.

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

>ls-output.txt 2>&1

перенаправляет стандартную ошибку в файл ls-output.txt, но при изменении порядка на

2>&1 >ls-output.txt

стандартная ошибка направлена на экран.

&>

Последние версии bash предоставляют второй, более упрощённый метод для выполнения комбинированного перенаправления 2>&1:

ls -l /bin/usr &> ls-output.txt

В этом примере мы используем одинарную запись &> для перенаправления как стандартного вывода, так и стандартной ошибки в файл ls-output.txt.

&>>

Вы также можете добавить стандартные выходные данные и стандартные потоки ошибок в один файл, например так:

ls -l /bin/usr &>> ls-output.txt

Итак, &> является аналогом 2>&1, а &>> это то же самое, но с перенаправлением вывода в файл.

<

Как мы уже рассмотрели выше, символ > является перенаправлением вывода. Что касается символа <, то он перенаправляет ввод. Используется следующим образом:

КОМАНДА1 < ФАЙЛ1

В этом случае КОМАНДА1 будет выполнена с ФАЙЛ1 в качестве источника ввода вместо клавиатуры, которая является обычным источником стандартного ввода.

Оператор < соответствует использованию | для передачи в программу стандартного ввода. Например, следующие команды являются идентичными:

КОМАНДА1 < ФАЙЛ1
cat ФАЙЛ1 | КОМАНДА1

Ещё один пример, содержимое файла math.txt:

cat math.txt
4*5

Тогда следующие команды идентичны:

bc < math.txt
# результат 20

echo '4*5' | bc
# результат 20

<<

Оператор << называется here document. С его помощью можно ввести строку состоящую из нескольких строк или присвоить переменной многострочное значение.

Если в консоль ввести

a=строка

и нажать Enter, то переменной a будет присвоено значение «строка» и вновь станет доступно приглашение командной строки, потому что Enter по умолчанию является разделителем, символом новой строки. Из-за этого не получится ввести многострочное значение.

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

К примеру:

cat <<_EOF_

Данная запись означает, что запущена команда cat, после неё идёт оператор << и последовательность символов _EOF_. Эти символы (_EOF_) + Enter означают, что _EOF_ - становится обозначением начала и конца для многострочных данных. То есть Enter больше не будет означать окончание ввода данных, в качестве обозначения окончания ввода данных будет выступать _EOF_. Вместо этих символов можно выбрать что угодно.

Второй ввод _EOF_ + Enter означает конец многострочных данных. После этого будет выполнена команда, то есть будут выведены введённые цифры:

cat <<_EOF_
1
2
3
_EOF_

Если вы хотите переменной присвоить многострочное значение, то это можно сделать примерно так:

a=`cat <<_EOF_
1
2
3
_EOF_
`

Выведем значение переменной:

echo "$a"

Here document это весьма полезная конструкция, к примеру, с её помощью можно делать шаблоны текста, меню, выводимых данных:

#!/bin/bash

userName="MiAl (Alex)"
site=ZaLinux.ru
status=admin

cat <<_EOF_
User: $userName
Web-site: $site
Role: $status
_EOF_

Вывод:

User: MiAl (Alex)
Web-site: ZaLinux.ru
Role: admin

<<<

Оператор <<< называется here string. Он передаёт с правой стороны стандартный ввод. Чтобы было понятно, следующие команды эквивалентны:

wc <<< 'just a string'
 1  3 14

'just a string' | wc
      1       3      14

Почему << (here document) и <<< (here string) нельзя использовать с переменными

Если мы захотим присвоить переменной значение с помощью рассмотренных операторов и попробуем выполнить:

a <<< 'just a string'

или

a <<< _EOF_

то будет получена ошибка:

bash: a: команда не найдена

Причина в том, что нельзя присвоить значение переменным передав данные в стандартном вводе. Например команда

echo 'just a string' | a

вызовет точно такую же ошибку.

А операторы << (here document) и <<< (here string) передают данные командам в стандартном вводе.

В чём различие << (here document) и <<< (here string)

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

<(КОМАНДА)

Конструкция <(КОМАНДА) называется «подстановка процессов» (Process Substitution). В качестве КОМАНДА может быть одна или более команд с аргументами. Конструкция

<(КОМАНДА)

вернёт имя специального файла, прочитав который можно получить вывод КОМАНДЫ.

К примеру:

echo <(ls -l)

выведет:

/dev/fd/63

Применение данного способа записи и чтения в и из команды показано далее.

Имеется ещё одна форма:

>(СПИСОК)

Если используется эта форма, запись в файл обеспечит ввод для КОМАНДЫ.

< <(КОМАНДА АРГУМЕНТЫ)

Данная конструкция состоит из двух уже рассмотренных ранее элементов языка Bash:

  • <(КОМАНДА АРГУМЕНТЫ)
  • <

Как мы только что узнали, <(КОМАНДА АРГУМЕНТЫ) возвращает имя файла из которого нужно считывать результат выполнения КОМАНДЫ. А оператор < передаёт ввод с файла (указанного справа от него) команде на стандартный ввод (указанной слева).

Следующие две команды являются аналогами друг друга:

grep drw < <(ls -l)
ls -l | grep drw

Практический пример использования из статьи «Как обработать каждую строку, полученную от команды grep»:

while read -r line ; do
    echo " Обрабатывается $line"
    # здесь ваш код
done < <(grep xyz abc.txt)

cat > ФАЙЛ <<_EOF_

Эта конструкция может показаться очень замысловатой, но она состоит из двух уже рассмотренных элементов:

  • > (перенаправление вывода в файл)
  • << (here document, то есть многострочный ввод)

Рассмотрим пример:

cat > ФАЙЛ <<_EOF_
foo
bar
bar bar
foo foo
_EOF_

В результате выполнения этого кода, в ФАЙЛ будут записаны строки

foo
bar
bar bar
foo foo

Причём если ФАЙЛ уже существует, то он будет стёрт и заменён указанным содержимым.

То есть это один из способов сохранения в файл многострочного вывода.

cat >> ФАЙЛ <<_EOF_

Эта конструкция похожа на предыдущую, в ней используются

  • >> (перенаправление вывода в файл с дописыванием данных)
  • << (here document, то есть многострочный ввод)

В результате выполнения следующего кода:

cat >> ФАЙЛ <<_EOF_
foo
bar
bar bar
foo foo
_EOF_

В ФАЙЛ будут сохранены строки:

foo
bar
bar bar
foo foo

Причём если ФАЙЛ уже существует, то он будет дописан.

cat <<_EOF_ > ФАЙЛ

Данная конструкция получает многострочный ввод по стандартному вводу и сохраняет его в файл. То есть это аналог

cat > ФАЙЛ <<_EOF_

в котором просто операторы поменяны местами.

К примеру, в следующем примере:

cat <<_EOF_ > num.txt
12345
67890
1011121314
_EOF_ 

В файл num.txt будут сохранены строки

12345
67890
1011121314

cat <<_EOF_ >> ФАЙЛ

Эта запись является аналогом

cat >> ФАЙЛ <<_EOF_

Следующим код

cat <<_EOF_ >> num.txt
12345
67890
1011121314
_EOF_

допишет файл num.txt строками

12345
67890
1011121314

Рекомендуемые статьи:

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

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