如何将标准输入中的多行输入读入变量以及如何在 shell(sh,bash) 中打印出来?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/212965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read mutliline input from stdin into variable and how to print one out in shell(sh,bash)?
提问by Tanktalus
What I want to do is the following:
我想要做的是以下内容:
- read in multiple line input from
stdin
into variableA
- make various operations on
A
- pipe
A
without losing delimiter symbols (\n
,\r
,\t
,etc) to another command
- 读入多行输入
stdin
到变量中A
- 进行各种操作
A
- 管
A
,而不会失去定界符符号(\n
,\r
,\t
等)到另一个命令
The current problem is that, I can't read it in with read
command, because it stops reading at newline.
当前的问题是,我无法使用read
命令读取它,因为它在换行符处停止读取。
I can read stdin with cat
, like this:
我可以用 读取标准输入cat
,如下所示:
my_var=`cat /dev/stdin`
, but then I don't know how to print it. So that the newline, tab, and other delimiters are still there.
,但后来我不知道如何打印它。这样换行符、制表符和其他分隔符仍然存在。
My sample script looks like this:
我的示例脚本如下所示:
#!/usr/local/bin/bash
A=`cat /dev/stdin`
if [ ${#A} -eq 0 ]; then
exit 0
else
cat ${A} | /usr/local/sbin/nextcommand
fi
回答by Tanktalus
This is working for me:
这对我有用:
myvar=`cat`
echo "$myvar"
The quotes around $myvar
are important.
周围的引号$myvar
很重要。
回答by Ingo Karkat
In Bash, there's an alternative way; man bash
mentions:
在 Bash 中,有另一种方式;man bash
提到:
The command substitution
$(cat file)
can be replaced by the equivalent but faster$(< file)
.
命令替换
$(cat file)
可以替换为等效但更快的$(< file)
。
$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
回答by Sergey Grigoriev
teedoes the job
t 恤做的工作
#!/bin/bash
myVar=$(tee)
回答by DocSalvager
[updated]
[更新]
This assignment will hang indefinitely if there is nothing in the pipe...
如果管道中没有任何东西,此任务将无限期挂起......
var="$(< /dev/stdin)"
We can prevent this though by doing a timeout read
for the first character. If it times out, the return code will be greater than 128 and we'll know the STDIN pipe (a.k.a /dev/stdin
) is empty.
我们可以通过read
为第一个字符设置超时来防止这种情况发生。如果超时,返回码将大于 128,我们就会知道 STDIN 管道(又名/dev/stdin
)是空的。
Otherwise, we get the rest of STDIN by...
否则,我们将获得 STDIN 的其余部分...
- setting
IFS
to NULL for just theread
command - turning off escapes with
-r
- eliminating read's delimiter with
-d ''
. - and finally, appending that to the character we got initially
IFS
仅为read
命令设置为 NULL- 关闭转义
-r
- 消除读取的分隔符
-d ''
。 - 最后,将它附加到我们最初得到的角色上
Thus...
因此...
__=""
_stdin=""
read -N1 -t1 __ && {
(( $? <= 128 )) && {
IFS= read -rd '' _stdin
_stdin="$__$_stdin"
}
}
This technique avoids using var="$(command ...)"
Command Substitution which, by design, will always strip off any trailing newlines.
这种技术避免使用var="$(command ...)"
命令替换,它在设计上总是会去掉任何尾随的换行符。
If Command Substitution is preferred, to preserve trailing newlines we can append one or more delimiter characters to the output inside the $()
and then strip them off outside.
如果首选命令替换,为了保留尾随换行符,我们可以将一个或多个定界符附加到输出内部$()
,然后将它们从外部剥离。
For example ( note $(parens)
in first command and ${braces}
in second )...
例如($(parens)
在第一个命令和${braces}
第二个命令中注意)......
_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
回答by DocSalvager
Yes it works for me too. Thanks.
是的,它也适用于我。谢谢。
myvar=`cat`
is the same as
是相同的
myvar=`cat /dev/stdin`
Well yes. From the bash
man page:
嗯,是。从bash
手册页:
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes.
双引号中的字符会保留引号内所有字符的字面值,但 $、`、\ 和启用历史扩展时的 ! 除外。字符 $ 和 ` 在双引号内保留其特殊含义。