发送字符串到标准输入


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
有效的意思是什么,为什么不通过管道进行此操作?
安迪

您列出的这两个命令应该执行完全相同的操作。你有什么问题
Flimzy 2011年

5
@Flimzy:afaik,第一个将无法正常运行,它将尝试打开一个名为echo
Andy

啊对。那么第二种形式有什么问题呢?
Flimzy 2011年

2
@Flimzy:此外,>重定向表单还将以fd 0(stdin)形式打开文件描述符,而|opens会启动子进程并将其stdout(fd 1)附加到另一个进程的stdin。这个事实可能会带来不小的后果(想分享环境变量吗?)
sehe 2011年

Answers:


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

以及如何以这种方式输入二进制值?不使用管道(我知道可以使用管道完成以下操作:echo -e "\x01\x02..." | ./script
cprcrack 2012年

我喜欢用另一种方式写它:<<<“这是来自stdin” perl ...,这样看起来像管道的左手边。
Pyrolistical,2014年

@Pyrolistical是!例如,从命令行掌握perl oneliner时特别有用-轻松编辑perl的参数,而无需使用光标向后移动。:)
jm666 2014年

@ jm666令人难过的是,昨天我才了解到,如果您使用bash别名,则只需使用command_alias <<<“ stdin string”的形式,否则它将说找不到命令
Pyrolistical 2014年

@ jm666我可以在<<<哪里了解更多信息?我很ham愧地承认我从未见过它,对此我完全感到迷惑。我尝试使用谷歌搜索,但结果无关。
wpcarro

66

你很亲密

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

对于多行输入,here-docs适用:

/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?

这是4字节二进制浮点数中前90度的正弦


以及如何以这种方式输入二进制值?
cprcrack

我会使用xxd -r(或od)过滤HERE文档
sehe 2012年

您可以举一个例子来解释吗?我没有做到。
cprcrack 2012年

1
查看修改后的答案。关键是不要在脚本中包含原始二进制数据,而应通过xxd之类的程序对其进行过滤
sehe 2012年

这样做的意义是:“ / my / bash / script <<<'此字符串将被发送到stdin。'”您可以直接说:“ / my / bash / script'此字符串将被发送到stdin。 '”?
Baiyan Huang

2

您也可以read这样使用

echo "enter your name"
read name
echo $name

2

您想要(1)在一个进程中创建stdout输出(如echo '…'),并且(2)将该输出重定向到另一进程的stdin输入,但是(3)不使用bash管道机制。这是一个符合所有三个条件的解决方案:

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

<是stdin的正常输入重定向。的<(…)是bash进程替换。大致/dev/fd/…用替换命令的输出创建一个文件,并将该文件名传递给,代替,<(…)例如在中得到的结果script < /dev/fd/123。有关详细信息,请参见此答案

与其他解决方案的比较

  • 发送到stdin的单行heredoc script <<< 'string'仅允许发送静态字符串,而不发送其他命令的输出。

  • 仅进程替换(例如in diff <(ls /bin) <(ls /usr/bin)中)不会将任何内容发送到stdin。而是将进程输出作为在后台创建的文件的内容传递,例如diff /dev/fd/10 /dev/fd/11。在该命令中,diff没有从stdin获得任何输入。

用例

我喜欢这样,与管道机制不同,该< <(…)机制允许将命令放在第一位,然后将所有输入放在命令后,这是命令行选项输入的标准。

但是,除了命令行美学之外,在某些情况下无法使用管道机制。例如,当某个命令必须作为另一个命令的参数提供时,例如在此示例中,带有sshpass


有趣的选择。难道这与POSIX兼容<<<吗?
所有工人都是必不可少的

0
cat | /my/bash/script

使您可以在程序中键入多行,而无需将该输入保存在历史记录中或在中看不到ps。完成输入后,只需按Ctrl +C cat


-1

别名可以也不能处理管道标准输入...

在这里我们创建3行输出

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

然后,将输出通过管道传递到sed命令的stdin,以将它们全部放在一行上

$ 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
>

首先,这不能回答问题-也许您回答了错误的问题?其次,为什么还要在别名中定义函数?你应该做function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }。第三,使用awk可以更容易理解该sed:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.