-1

If I run this, it work.

dig +short myip.opendns.com @resolver1.opendns.com

If I did this, it is not working

ip=$(dig +short myip.opendns.com @resolver1.opendns.com) | echo "$ip"

How to pass variable through pipe command?

code-8
  • 54,650
  • 106
  • 352
  • 604
  • I don't quite get it.. Why do you need to pass it? How is it different from: ip="dig"+"short myip.opendns.com @resolver1.opendns.com" ; echo $ip – StupidWolf Oct 25 '19 at 12:15

4 Answers4

8

You don't.

Use

ip=$(dig +short myip.opendns.com @resolver1.opendns.com) && echo "$ip"

(won't echo if first command fails)

Or

ip=$(dig +short myip.opendns.com @resolver1.opendns.com); echo "$ip"

(echo $ip anyway)

Corentin Limier
  • 4,946
  • 1
  • 13
  • 24
  • 1
    yes, agree with these. You can't use a pipe because the OS basically "runs" all of the commands in the pipeline at once, sending std-out of one, onto the std-in of the next. `$ip` is "decided" yet, so there is nothing to pass between the two programs. Good luck. – shellter Oct 25 '19 at 12:27
1

The very short version is that a pipe connects the standard output of one (set of) command(s) to the standard input of another. It can be tricky to understand the nuances of actual pipes though. In your example I'm not entirely clear where the variable assignment takes place as the variable does not exist in the current shell (or the echo would be able to use it).

Regardless, your construct would pipe the standard output of the variable assignment to the input of echo. The standard output of a variable assignment I take to be nothing (if you assign a variable you get no output on your command line).

I found a very detailed explanation of pipes in bash (Unix) here:

What is a simple explanation for how pipes work in Bash?

Look especially at the answer provided by rkachach.

Also, the pipeline that you have created (and which Corentin Limier has improved in that excellent reply) is not very robust as a test. Take for example this scenario where the command loading ip errors:

$ ip=$(dig +short myip.opendns.co @resolver1.opendns.co) && echo "$ip" 
dig: couldn't get address for 'resolver1.opendns.co': not found

As you can see the error (standard error from the dig command) is loaded into ip, and this test fails to manage that.

JamesIsIn
  • 181
  • 1
  • 6
1

I believe you are mixing up two things here: the usage of pipes and the usage of variables.

Let me give you a simple example of a pipe:

grep "Something" filename.txt | sort

As you can see, a pipe means "Take the output of one command and use it as input for the following one", in this case: filter the file on one particular word, and sort it alphabetically.

Let me give you a simple example of a variable:

ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
do_something_else
echo $ip

As you see, this looks more like a part of a script where you need to store some information that you won't use immediately.

So, in a nutshell: if you want to use the output of a command immediately as input for a next command (which might also immediately be used for another next command, ...), then a pipe is useful.
If, however, you want to do more complex things (like holding on to a result for not-immediate usage), you might use a variable.

Dominique
  • 16,450
  • 15
  • 56
  • 112
1

For completeness, the assignment is actually completely lost using the syntax you have used.

Normally, if you were to do

i=$(echo 20)

Then a fork is launched to run echo 20 and the output from that fork is used by the main code to assign i, a local variable. Everything else in the fork is forgotten, as usual.

When you do

echo 10 | echo $i

What happens is 2 forks are launched, one for each echo command and the output of 1 is connected to the input of the other. Nothing is kept from that operation. Note also that the value for $i is resolved before either of the two forks are actually launched.

When you do

i  = $(echo 20) | echo $i

One fork is launched to perform i = $(echo 20). That in turn launches a fork to do echo 20.

Another fork is launched to do echo $i and the value of $i is completely resolved before either is kicked off.

The first fork stores a local value i, but that is forgotten when that fork exits!

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27