How to read mutliline input from stdin into variable and how to print one out in shell(sh,bash)?

穿精又带淫゛_ 提交于 2019-11-29 20:23:57
Tanktalus

This is working for me:

myvar=`cat`

echo "$myvar"

The quotes around $myvar are important.

In Bash, there's an alternative way; man bash mentions:

The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test

tee does the job

#!/bin/bash
myVar=$(tee)

Yes it works for me too. Thanks.

myvar=`cat`

is the same as

myvar=`cat /dev/stdin`

Well yes. From the bash man page:

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.

If you do care about preserving trailing newlines at the end of the output, use this:

myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"

This uses the trick from here.

[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.

Otherwise, we get the rest of STDIN by...

  • setting IFS to NULL for just the read command
  • turning off escapes with -r
  • eliminating read's delimiter with -d ''.
  • and finally, appending that to the character we got initially

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.

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 )...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!