What I want to do is the following:
stdin
into variable A
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...
IFS
to NULL for just the read
command-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.
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%|||}"
tee does the job
#!/bin/bash
myVar=$(tee)
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
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.
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.
This is working for me:
myvar=`cat`
echo "$myvar"
The quotes around $myvar
are important.