Трубопровод не работает с командой echo

Когда я запускаю следующий Bash script, я ожидаю, что он напечатает Hello. Вместо этого он печатает пустую строку и выходит.

echo 'Hello' | echo

Почему не работает piping с echo до echo?

Ответ 1

echo печатает все свои аргументы. Он не читается из stdin. Таким образом, второй echo печатает все свои аргументы (none) и выходит, игнорируя Hello on stdin.

Для программы, которая читает ее stdin и печатает ее на stdout, используйте cat:

$ echo Hello | cat
Hello

Ответ 2

Кажется, вы не понимаете трубы. В этом случае они более точно известны как анонимные трубы, потому что у них нет имени (есть и именованные каналы). Анонимные трубы работают только между связанными процессами, например с процессами с одним и тем же родителем.

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

Первые три потока, используемые (называемые файловыми дескрипторами), пронумерованы 0, 1 и 2. Первый, 0, известен как стандартный ввод или stdin (имя, используемое в C). По умолчанию это связано с клавиатурой, но ее можно перенаправить либо с помощью символа <, либо с именем программы, находящимся на правой стороне канала.

Второй, 1, известен как стандартный вывод или stdout. По умолчанию это связано с экраном терминала, но может быть перенаправлено с помощью символа > или имени программы, расположенного на левой стороне канала.

Итак:

echo 'Hello' | echo

принимает стандартный вывод из echo и передает его на стандартный ввод echo. Но echo не читает stdin! Так что ничего не происходит.

Фильтровать программы обрабатывают имена файлов, указанные в командной строке. Если имена файлов не указаны, они читают stdin. Примеры включают cat, grep и sed, но не echo. Например:

echo 'Hello' | cat

отобразит "Hello", а cat бесполезен (это часто бывает).

echo 'Hello' | cat file1

будет игнорировать вывод из echo и просто отобразить содержимое файла1. Помните, что stdin читается только в том случае, если имя файла не указано.

Как вы думаете, что это отображается?

echo 'Hello' | cat < file1 file2

и почему?

Наконец, третий поток, 2, называется стандартной ошибкой или stderr, и этот небуферизован. Он игнорируется трубами, потому что они работают только между stdin и stdout. Однако вы можете перенаправить stderr на использование stdout (см. man dup2):

myprog 2>&1 | anotherprog

2>&1 означает "перенаправить файловый дескриптор 2 на то же место, что и дескриптор 1".

Это нормальное поведение, однако программа может переопределить все, что захочет. Например, он мог читать из дескриптора файла 2. Я опустил много других деталей, включая другие формы перенаправления, такие как замещение процессов и здесь документы.

Ответ 3

Трубопровод может выполняться только для команд, принимающих входы от stdin. Но эхо не берется из stdin. Он будет принимать входные данные из аргумента и печатать его. Так что это не сработает. Inorder to echo вы можете сделать что-то вроде echo $(echo 'hello')

Ответ 4

Это потому, что echo (как встроенный, так и /bin/echo) ничего не читает из stdin.

Вместо этого используйте cat:

echo 'Hello' | cat
Hello

Или без труб:

cat <<< 'Hello'