7

I'm trying to get better at one-liners here, this is what I have currently.

$ echo $PATH
/home/ubuntu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

What I want to do is strip off that first chunk, so here's what I've figured out so far ---

$ echo $PATH | sed -e "s|^/[A-Za-z/]*:||"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

The last thing I want to do here is to put that back into PATH, like export PATH=[that result]

The way I've tried this was as follows, which I can't get to work ---

$ echo $PATH | sed -e "s|^/[A-Za-z/]*:||" | xargs export PATH=
xargs: export: No such file or directory

Also, BTW, separate issue that confused me was with the sed expression above, for some reason when I tried using + rather than *, it wouldn't catch the first bit. Look ---

$ echo $PATH | sed -e "s|^/[A-Za-z/]+:||" 
/home/ubuntu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Its like the +, meaning "one or more" doesn't work as well as the "many" *.

David Jashi
  • 4,490
  • 1
  • 21
  • 26
Tom
  • 330
  • 4
  • 15

3 Answers3

11

I think the best solution for that particular problem is:

export PATH=${PATH#*:}

But that doesn't answer the question of how to use stdin to set an environment variable.

It's easy to use some process' stdout:

export PATH=$(make_new_path)

But that's not strictly speaking using stdin. The obvious solution:

make_new_path | export PATH=$(cat)

won't work because the commands to the right of the pipe are executed in a subshell, so variable settings won't stick. (If it had worked, it would have been an UUOC.)

As Gordon Davisson points out in a comment, you could simply use:

read -r PATH; export PATH

Also, it is actually not necessary to export PATH, since PATH comes pre-exported, but I left it in for the case where you want to use some other environment variable.

rici
  • 234,347
  • 28
  • 237
  • 341
  • If he actually wanted to use STDIN of the script, rather than STDOUT of some command, the proper thing to use would be `read PATH` -- but that's not what's needed here at all. – Gordon Davisson Jul 09 '13 at 07:22
  • 1
    @GordonDavisson: good point. I'll fix that. It's not what is needed here, but it is the title of the question. – rici Jul 09 '13 at 07:25
  • If you wanted to be ridiculous (and incompatible with anything but bash), you could use process redirection: `read PATH < <(make_new_path)` – Gordon Davisson Jul 09 '13 at 07:27
  • +1 I think he really meant STDOUT and wrote STDIN by mistake. You did right to answer the *intent*, not the question literally. It's also nice you added the `read -r` option. – janos Jul 09 '13 at 09:24
  • Could also add "-s" to the read to suppress echoing. – Ben Aveling Apr 27 '22 at 02:16
2
export PATH=$(echo "$PATH" | sed -e "s|^/[A-Za-z/]*:||")

export is a shell built-in; that's why you can't execute it directly via xargs (there isn't an executable for export). This runs your edit script and sets the value as the new value of $PATH. As written with double quotes around $PATH, it works even there are multiple adjacent spaces in an element of your PATH (fairly unlikely, but no harm in making sure it works properly).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • `echo $var` and `echo "$var"` are the same. You don't need those quotes. Also, `z=$(echo a b)` is the same as `z="$(echo a b)"` and `z="$(echo "a b")"`. – janos Jul 09 '13 at 07:03
  • 2
    @janos, `echo "$var"` is very different from `echo $var` -- try it yourself with `var='*'`, or more subtly with `var="two spaces"` (with 2 spaces between the words). bash allows you to omit the double quotes for variable assignment. – glenn jackman Jul 09 '13 at 09:22
  • @glennjackman Damn, you're right! I also overlooked the "multiple adjacent spaces" bit, my bad, and thanks for the note! – janos Jul 09 '13 at 09:34
1

This is a bit more simple and accurate:

echo "$PATH" | sed -e s/[^:]*://

The regular expression there is more accurate, it will work even if the first segment has numbers or spaces in it.

Btw, you do NOT need to export, because PATH is already exported.

The implementation of regular expressions depends on the tool. As far as I know + does not work in sed, you can do this instead:

echo "$PATH" | sed -e 's/[^:]\{1,\}://'

It seems to me that regular expressions in sed work similar to vim and different from perl.

janos
  • 120,954
  • 29
  • 226
  • 236