2

How would I make a pipe insert characters into the middle of a string? Here's my example (running Raspian):

hostname -I | sudo python ~/testsite/manage.py runserver {the ip from the first command}:80

Is this possible? Also, please note that I would not like to use a static IP.

2 Answers2

6

I don't think you want to do what you're asking to do. If all you want is the output of one command used as the argument of another command, then structures like $(...) or `...` are your friend. For example:

sudo python ~/testsite/manage.py runserver $(hostname -I):80

Note that this is NOT what you asked for, but it does what you want.

If you really want stdin (a pipe) to be used as an argument, you may be able to use xargs(1) or a quick while loop in your shell.

This puts stdin at the end of the line:

echo Hello | xargs echo "The word is:"

or if you want to substitute something inside the line:

echo Hello | xargs -J % echo % is the word.

But xargs can be tricky to use if you're not able to understand its (somewhat arcane) usage. The xargs command also varies from OS to OS; the -J option works in BSD and OSX, but not in some older Linux distros. I don't know what OS you are using.

A loop might be easier:

echo Hello | while read word; do echo "$word is the word."; done

Or in your case:

hostname -I | while read ip; do
    sudo python ~/testsite/manage.py runserver ${ip}:80
done

The loop only gets run once, but you can put together your command line a little more easily. YMMV.

ghoti
  • 6,602
  • I don't quite understand what benefits does your approach have over command substitution as suggested by jordanm. – Dmitry Grigoryev Nov 18 '15 at 16:44
  • I prefer jordanm's answer over this. I don't see the point in looping over a single word. – Colby Gallup Nov 18 '15 at 16:50
  • I'm using Raspian (a version of Debian). – Colby Gallup Nov 18 '15 at 16:56
  • I prefer jordanm's solution over this also, but your question was explicit about using a pipe, so that was the answer I provided. Given this clarification that you're open to solutions beyond what you asked for, I've updated my answer. As for the point of running a single loop, as I said in the answer, using a loop allows you to use a variable as your stdin rather than having to use xargs' arcane non-portable character replacement technique. – ghoti Nov 18 '15 at 18:03
-2

I think you can use a dash which stands for the standard output from the previous command "hostname -I"

hostname -I | sudo python ~/testsite/manage.py runserver -

If you want to cut ipv6:

hostname -I | some command to cut ipv6 |sudo python ~/testsite/manage.py runserver -
  • dash must be explicitely supported by manage.py for this to work. Also, appending ':80' to the output of hostname would be problematic. – Dmitry Grigoryev Nov 18 '15 at 15:15
  • I think it is not related to manage.py. The dash in the pipeline has a special meaning. I think before manage.py is executed, the dash will be replaced by the ipv4 obtained by previous commands. – bitsoal Nov 18 '15 at 15:30
  • I certainly don't think it's true. Do you have a reference on dash having a special meaning on command line? – Dmitry Grigoryev Nov 18 '15 at 15:35
  • http://stackoverflow.com/questions/14199193/dash-redirect-from-stdin-to-stdout – bitsoal Nov 18 '15 at 15:43
  • That only works because file supports the dash. See http://unix.stackexchange.com/questions/16357/usage-of-dash-in-place-of-a-filename – Dmitry Grigoryev Nov 18 '15 at 16:01
  • 1
    The dash is an argument to the command it follows. It's not a special character, like a variable or a pathname, which can be expanded into something else. There is a convention to allow the dash to denote a file that is actually stdin, but it is by no means universal, or enforced. Also, if supported, the dash would allow stdin to be the INPUT to the manage.py command, not an OPTION to it. – ghoti Nov 18 '15 at 16:12
  • @DmitryGrigoryev - I know what the ':80' does. It's okay. – Colby Gallup Nov 18 '15 at 16:39