For simplicity I would like to do:
echo cart | assign spo;
echo $spo
Output: cart
Does such an assign application exist?
I am aware of all the ways to do this using substitution.
You could do something like this, if you use bash:
echo cart | while read spo; do echo $spo; done
Unfortunately, variable "spo" won't exist outside of the while-do-done loop. If you can get what you want done inside the while-loop, that will work.
You can actually do almost exactly what you wrote above in ATT ksh (not in pdksh or mksh) or in the fabulous zsh:
% echo cart | read spo
% echo $spo
cart
So, another solution would be to use ksh or zsh.
mksh): echo cart |& while read -p spo; do echo $spo; done (actually better to use while IFS= read -p -r spo; do… though)
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }
Would work (store the output of echo without the trailing newline character into the spo variable) as long as echo outputs only one line.
You could always do:
assign() {
eval "$1=\$(cat; echo .); $1=\${$1%.}"
}
assign spo < <(echo cart)
The following solutions would work in bash scripts, but not at the bash prompt:
shopt -s lastpipe
echo cat | assign spo
Or:
shopt -s lastpipe
whatever | IFS= read -rd '' spo
To store the output of whatever up to the first NUL characters (bash variables can't store NUL characters anyway) in $spo.
Or:
shopt -s lastpipe
whatever | readarray -t spo
to store the output of whatever in the $spo array (one line per array element).
IFS= and read?
If I understand the issue correctly you want to pipe stdout to a variable. At least that was what I was looking for and ended up here. So for those who share my fate:
spa=$(echo cart)
Assigns cart to the variable $spa.
If you just want to output the current pipe stream use cat.
echo cart | cat
If you want to continue your command chain, try using the tee command to echo the output.
echo cart | tee /dev/tty | xargs ls
You could use an alias to shorten the command.
alias tout='tee /dev/tty'
echo cart | tout | xargs ls
cat?
echo | cat construct threw me.
Here's my solution to the problem.
# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
# b.) aliases don't take arguments, but we write this so that the "argument" appears
# behind the alias, making it appear as though it is taking one, which in turn
# becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"
If you are willing to use a temporary file you can avoid substitution and the expensive pipe.
echo cart > tmp.$$; read spo < tmp.$$; rm tmp.$$
Fun shell fact: you can even move the redirection operator to the front for improved "pipe" feeling:
echo cart > tmp.$$; < tmp.$$ read spo
A=$( some | command | here )with each ofsome |,command |, andhereon its own line.