Отправить строку в stdin

158

Есть ли способ эффективно сделать это в Bash:

/my/bash/script < echo 'This string will be sent to stdin.'

Я знаю, что мог бы передать вывод от эха, такого как это:

echo 'This string will be piped to stdin.' | /my/bash/script
Все работники необходимы
источник
1
Что вы имеете в виду под эффективным , почему не труба способ сделать это?
Энди
Обе команды, перечисленные вами, должны выполнять одно и то же. Какие у вас проблемы?
Хлипкий
5
@Flimzy: afaik, первый не будет работать должным образом, он попытается открыть файл с именемecho
Энди
О верно. Так что не так со второй формой?
Хлипкий
2
@Flimzy: кроме того, >форма перенаправления откроет дескриптор файла как fd 0(stdin), тогда как |opens запускает дочерний процесс и присоединяет его stdout (fd 1) к stdin другого процесса. Этот факт может иметь нетривиальные последствия (думать о разделении переменных окружения?)
sehe

Ответы:

262

Вы можете использовать одну линию heredoc

cat <<< "This is coming from the stdin"

выше то же самое, что

cat <<EOF
This is coming from the stdin
EOF

или вы можете перенаправить вывод из команды, как

diff <(ls /bin) <(ls /usr/bin)

или вы можете прочитать как

while read line
do
   echo =$line=
done < some_file

или просто

echo something | read param
jm666
источник
И как таким образом вводить двоичные значения? Без использования трубы (я знаю , что это можно сделать с помощью трубы следующим образом : echo -e "\x01\x02..." | ./script)
cprcrack
Мне нравится писать это по-другому: <<< "Это исходит от стандартного ввода" perl ..., таким образом, это выглядит как левая часть канала.
пиролистический
@ Пиролистический да! Особенно полезно при освоении, например, perl oneliner из командной строки - простое редактирование аргументов perl без необходимости большого перемещения назад с помощью курсора. :)
jm666
@ jm666 Печально то, что я узнал вчера, что если вы используете псевдоним bash, вы просто используете форму command_alias <<< "stdin string", в противном случае он скажет, что команда не найдена
Pyrolistical
@ jm666 Есть ли где-нибудь, о чем я могу узнать больше <<<? Мне стыдно признаться, что я никогда не видел этого раньше, и я полностью озадачен этим. Я попробовал Googling для этого, но мои результаты не были связаны.
wpcarro
66

Вы были близки

/my/bash/script <<< 'This string will be sent to stdin.'

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

/my/bash/script <<STDIN -o other --options
line 1
line 2
STDIN

Редактировать К комментариям:

Для достижения двоичного ввода, скажем

xxd -r -p <<BINARY | iconv -f UCS-4BE -t UTF-8 | /my/bash/script
0000 79c1 0000 306f 0000 3061 0000 3093 0000 3077 0000 3093 0000 304b 0000 3093 0000 3077 0000 3093 0000 306a 0000 8a71 0000 306b 0000 30ca 0000 30f3 0000 30bb
0000 30f3 0000 30b9 0000 3092 0000 7ffb 0000 8a33 0000 3059 0000 308b 0000 3053 0000 3068 0000 304c 0000 3067 0000 304d 0000 000a
BINARY

Если заменить catна /my/bash/script(или даже уронить последнюю трубку), это печатает:

私はちんぷんかんぷんな話にナンセンスを翻訳することができ

Или, если вы хотите что-то более вызывающее:

0000000: 0000 0000 bef9 0e3c 59f8 8e3c 0a71 d63c  .......<Y..<.q.<
0000010: c6f2 0e3d 3eaa 323d 3a5e 563d 090e 7a3d  ...=>.2=:^V=..z=
0000020: 7bdc 8e3d 2aaf a03d b67e b23d c74a c43d  {..=*..=.~.=.J.=
0000030: 0513 d63d 16d7 e73d a296 f93d a8a8 053e  ...=...=...=...>
0000040: 6583 0e3e 5a5b 173e 5b30 203e 3d02 293e  e..>Z[.>[0 >=.)>
0000050: d4d0 313e f39b 3a3e 6f63 433e 1c27 4c3e  ..1>..:>ocC>.'L>
0000060: cde6 543e 59a2 5d3e 9259 663e 4d0c 6f3e  ..T>Y.]>.Yf>M.o>
0000070: 60ba 773e cf31 803e ee83 843e 78d3 883e  `.w>.1.>...>x..>
0000080: 5720 8d3e 766a 913e beb1 953e 1cf6 993e  W .>vj.>...>...>
0000090: 7a37 9e3e c275 a23e dfb0 a63e bce8 aa3e  z7.>.u.>...>...>
00000a0: 441d af3e 624e b33e 017c b73e 0ca6 bb3e  D..>bN.>.|.>...>
00000b0: 6fcc bf3e 15ef c33e e90d c83e d728 cc3e  o..>...>...>.(.>
00000c0: c93f d03e ac52 d43e 6c61 d83e f36b dc3e  .?.>.R.>la.>.k.>
00000d0: 2f72 e03e 0a74 e43e 7171 e83e 506a ec3e  /r.>.t.>qq.>Pj.>
00000e0: 945e f03e 274e f43e f738 f83e f11e fc3e  .^.>'N.>.8.>...>
00000f0: 0000 003f 09ee 013f 89d9 033f 77c2 053f  ...?...?...?w..?
0000100: caa8 073f 788c 093f 776d 0b3f be4b 0d3f  ...?x..?wm.?.K.?
0000110: 4427 0f3f 0000 113f e8d5 123f f3a8 143f  D'.?...?...?...?
0000120: 1879 163f 4e46 183f 8d10 1a3f cad7 1b3f  .y.?NF.?...?...?
0000130: fe9b 1d3f 1f5d 1f3f 241b 213f 06d6 223f  ...?.].?$.!?.."?
0000140: bb8d 243f 3a42 263f 7cf3 273f 78a1 293f  ..$?:B&?|.'?x.)?
0000150: 254c 2b3f 7bf3 2c3f 7297 2e3f 0138 303f  %L+?{.,?r..?.80?
0000160: 22d5 313f ca6e 333f                      ".1?.n3?

Что является синусом первых 90 градусов в 4-байтных двоичных числах?

sehe
источник
И как таким образом вводить двоичные значения?
cprcrack
Я бы использовал xxd -r(или od), чтобы отфильтровать ЗДЕСЬ документ
смотри
Не могли бы вы объяснить это на примере? Мне не удалось это сделать.
cprcrack
1
см. отредактированный ответ. Смысл в том, чтобы не включать необработанные двоичные данные в ваш скрипт, а вместо этого фильтровать их через такую ​​программу, как xxd
sehe
Какой смысл делать: "/ my / bash / script <<< 'Эта строка будет отправлена ​​в stdin.'" Когда вы можете прямо сказать: "/ my / bash / script" Эта строка будет отправлена ​​в stdin. '"?
Байян Хуан
2

Вы также можете использовать readкак это

echo "enter your name"
read name
echo $name
Рахул
источник
2

Решение

Вы хотите (1) создать вывод stdout в одном процессе (например echo '…') и (2) перенаправить этот вывод на ввод stdin другого процесса, но (3) без использования механизма bash pipe. Вот решение, которое соответствует всем трем условиям:

/my/bash/script < <(echo 'This string will be sent to stdin.')

<Является нормальным для перенаправления ввода стандартного ввода. Это <(…)замена процесса bash. Примерно он создает /dev/fd/…файл с выводом замещающей команды и передает это имя файла вместо <(…), приводя здесь, например, в script < /dev/fd/123. Подробнее см. Этот ответ

Сравнение с другими решениями

  • Однострочный heredoc, отправляемый в stdin, script <<< 'string'позволяет отправлять только статические строки, но не выводить другие команды.

  • Одна только подстановка процесса, например, in diff <(ls /bin) <(ls /usr/bin), ничего не отправляет в stdin. Вместо этого выходные данные процесса передаются как содержимое файлов, созданных в фоновом режиме, что эквивалентно, например diff /dev/fd/10 /dev/fd/11,. В этой команде diffне получает ввода от stdin.

Случаи использования

Мне нравится это, в отличие от конвейерного механизма, < <(…)механизм позволяет помещать команду первым и весь ввод после нее, как стандарт для ввода из параметров командной строки.

Однако, помимо эстетики командной строки, в некоторых случаях нельзя использовать механизм трубы. Например, когда определенная команда должна быть предоставлена ​​в качестве аргумента другой команде, например, в этом примере сsshpass .

tanius
источник
Интересная альтернатива. Это в отличие от POSIX <<<?
Все работники необходимы
0
cat | /my/bash/script

Позволяет вводить в программу несколько строк, не сохраняя эти данные в истории и не видя их в ps. Просто нажмите Ctrl + C, когда закончите печатать, чтобы закончить cat.

WALF
источник
-1

псевдонимы могут и не могут обрабатывать стандартный канал ...

Здесь мы создаем 3 строки вывода

$ echo -e "line 1\nline 2\nline 3"
line 1
line 2
line 3

Затем мы направляем вывод в stdin команды sed, чтобы поместить их все в одну строку

$ echo -e "line 1\nline 2\nline 3" |  sed -e ":a;N;\$!ba ;s?\n? ?g"
line 1 line 2 line 3

Если мы определим псевдоним той же команды sed

$ alias oline='sed -e ":a;N;\$!ba ;s?\n? ?g"'

Мы можем передать вывод на стандартный ввод псевдонима, и он ведет себя точно так же

$ echo -e "line 1\nline 2\nline 3" |  oline
line 1 line 2 line 3

Проблема возникает, когда мы пытаемся определить псевдоним как функцию

$ alias oline='function _oline(){ sed -e ":a;N;\$!ba ;s?\n? ?g";}_oline'

Определение псевдонима как функции разрывает канал

$ echo -e "line 1\nline 2\nline 3" |  oline
>
KeNB
источник
Во-первых, это не отвечает на вопрос - может быть, вы ответили не на тот вопрос? Во-вторых, зачем вам определять функцию внутри псевдонима? Вы должны просто сделать function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. В-третьих, этот sed был бы намного более понятен с помощью awk:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Леонардо Дагнино