I have some scripts that work with parameters, they work just fine but i would like them to be able to read from stdin, from a pipe for example, an example, suppose this is called read:
#!/bin/bash function read() { echo $* } read $*
Now this works with read "foo" "bar"
, but I would like to use it as:
echo "foo" | read
How do I accomplish this?
Bash Redirection STDIN, STDOUT and STDERR explained Standard input is used to provide input to a program. (Here we're using the read builtin to read a line from STDIN.) STDOUT root@server~# ls file file. Standard output is generally used for "normal" output from a command.
What is read? Read is a bash builtin command that reads the contents of a line into a variable. It allows for word splitting that is tied to the special shell variable IFS. It is primarily used for catching user input but can be used to implement functions taking input from standard input.
To pass any number of arguments to the bash function simply put them right after the function's name, separated by a space. It is a good practice to double-quote the arguments to avoid the misparsing of an argument with spaces in it. The passed parameters are $1 , $2 , $3 …
It's a little tricky to write a function which can read standard input, but works properly when no standard input is given. If you simply try to read from standard input, it will block until it receives any, much like if you simply type cat
at the prompt.
In bash 4, you can work around this by using the -t
option to read
with an argument of 0. It succeeds if there is any input available, but does not consume any of it; otherwise, it fails.
Here's a simple function that works like cat
if it has anything from standard input, and echo
otherwise.
catecho () { if read -t 0; then cat else echo "$*" fi } $ catecho command line arguments command line arguments $ echo "foo bar" | catecho foo bar
This makes standard input take precedence over command-line arguments, i.e., echo foo | catecho bar
would output foo
. To make arguments take precedence over standard input (echo foo | catecho bar
outputs bar
), you can use the simpler function
catecho () { if [ $# -eq 0 ]; then cat else echo "$*" fi }
(which also has the advantage of working with any POSIX-compatible shell, not just certain versions of bash
).
You can use <<<
to get this behaviour. read <<< echo "text"
should make it.
Test with readly
(I prefer not using reserved words):
function readly() { echo $* echo "this was a test" } $ readly <<< echo "hello" hello this was a test
With pipes, based on this answer to "Bash script, read values from stdin pipe":
$ echo "hello bye" | { read a; echo $a; echo "this was a test"; } hello bye this was a test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With