21

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.

  • Why do you want to do this without substitution? – Thanatos Nov 8 '13 at 19:08
  • I like the reverse Polish notation flow when writing with pipes only. I am much faster coding and the codes quality / speed is not so important. Also I don't when chaining it is hella easier to comment out parts of the chain and echo the current output rather then erase ticks etc. – James Nov 8 '13 at 19:51
  • If you're concerned about ease of debugging, consider putting the backticks command on a series of separate lines. A=$( some | command | here ) with each of some |, command |, and here on its own line. – roaima Jan 26 '15 at 22:59
12
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).

| improve this answer | |
  • 1
    shouldn't there be a space between IFS= and read? – caesarsol Apr 23 '15 at 13:36
  • All hail last pipe . Also side note set +m ( ermmm or -m ) is needed from a command line she'll as last pipe does not work with job control active . – James Oct 2 '15 at 3:43
17

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.

| improve this answer | |
  • 1
    You can use coprocesses in the Korn Shell (e.g. mksh): echo cart |& while read -p spo; do echo $spo; done (actually better to use while IFS= read -p -r spo; do… though) – mirabilos Feb 27 '14 at 14:03
3

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.

| improve this answer | |
  • 2
    That's what they call substitution, which the OP wanted to avoid. – Dmitry Grigoryev Sep 30 '15 at 20:20
  • This was useful to me, i just needed to assign it to a variable, i didn't care how it got there! – Chris Marisic Apr 24 '19 at 19:37
  • The shell does indeed pipe the output of the command to the variable. It ALSO pipes stdin into the command. This can mess up while loops that read input, and cause them to exhaust stdin and quit reading after one loop. This is a baffling situation -- no error occurs and no indication of what is the matter is exported. You must explicitly redirect stdin from /dev/null to prevent the loop from stopping at one iteration. out=$( prog </dev/null arg1 arg2 ...) # does the trick. Just putting this here to be stumbled upon someday and make someone's day. – Chris Reid Jan 4 at 6:30
1

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
| improve this answer | |
  • Why would you want to pipe output to a plain cat? – roaima Jan 26 '15 at 22:57
  • 1
    @roaima Some command recognize they are running on a terminal an behave differently than if they are outputting to a pipe. In particular they may truncate lines to the current screen width. For most command the cat command is redundant. – BillThor Jan 27 '15 at 0:32
  • Ah ok, I see now what you were trying to illustrate. The echo | cat construct threw me. – roaima Jan 27 '15 at 0:35
1

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"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.