有没有一种方法可以在bash中有效地做到这一点:

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

我知道我可以从echo输出这样的管道:

echo 'This string will be piped to stdin.' | /my/bash/script

当前回答

你也可以像这样使用read

echo "enter your name"
read name
echo $name

其他回答

您可以使用单行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
cat | /my/bash/script

允许在程序中输入多行,而输入不会被保存在历史记录中,也不会在ps中可见。以换行符结束,然后按Ctrl + D结束cat。

你也可以像这样使用read

echo "enter your name"
read name
echo $name

解决方案

你想(1)在一个进程中创建stdout输出(如echo '…'),(2)将输出重定向到另一个进程的stdin输入,但(3)不使用bash管道机制。下面是一个同时满足这三个条件的解决方案:

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

<是stdin的正常输入重定向。<(…)是bash进程替换。粗略地说,它用替换命令的输出创建了一个/dev/fd/…文件,并将该文件名传递给<(…),例如在脚本< /dev/fd/123中详情请参见此回答。

与其他方案的比较

发送给stdin脚本<<< 'string'的一行heredoc只允许发送静态字符串,而不是其他命令的输出。 单独的进程替换,例如在diff <(ls /bin) <(ls /usr/bin)中,不会向stdin发送任何内容。相反,流程输出被保存到一个文件中,其路径作为命令行参数传递。对于上面的例子,这相当于diff /dev/fd/10 /dev/fd/11,一个命令,其中diff没有从stdin接收输入。

用例

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

然而,除了命令行美学之外,还有一些情况下不能使用管道机制。例如,当某个命令必须作为另一个命令的参数提供时,例如本例中的sshpass。

别名可以或不能处理管道stdin… 这里我们创建了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
>