Here is my interesting sed question:
echo "/usr/bin:/etc:/usr/local/bin:/opt:/opt/bin" | sed "s?/usr.*:??g"
What I wanted to see for sed "s?/usr.*:??g" is to remove any
directories containing "/usr" from the string. The correct result
should be like:
/etc:/opt/:/opt/bin
However, the above sed command doesn't do what I wanted, it returns
the last directory only.
/opt/bin
so apparently the colon (:) in the sed command matches the last one
in the string, not the first one after the pattern. How do I fix it?
Thanks in advance,
Limin.
That's happening because .* is greedy and matches up to the end of the
string, and then sed backtracks to find the next matching character.
To fix it, change to "s?/usr[^:]*:??g"
Cheers,
Chris
As others have said the * quantifier is greedy so you could use
$ echo "/usr/bin:/etc:/usr/local/bin:/opt:/opt/bin" | sed -e
's?/usr[^:]*:??g'
/etc:/opt:/opt/bin
But that won't work correctly if the last entry contains '/usr'
$ echo "/opt/bin:/opt:/usr/local/bin:/etc:/usr/bin" | sed -e
's?/usr[^:]*:??g'
/opt/bin:/opt:/etc:/usr/bin
So you could try it like this
$ echo "/opt/bin:/opt:/usr/local/bin:/etc:/usr/bin" | sed -e
's?/usr[^:]*\(:\|$\)??g'
/opt/bin:/opt:/etc:
But that leaves a ':' at the end of the string
$ echo "/opt/bin:/opt:/usr/local/bin:/etc:/usr/bin" | sed -e
's?/usr[^:]*\(:\|$\)??g' -e 's?:$??'
/opt/bin:/opt:/etc
John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
The \(..\|...\) alternation syntax is not standard.
The above also removes a trailing : that would have been there
from the start. It also removes /usr in /opt/usrank/...
sed '
s,^,:,
s,:/usr[^:]*,,g
s,^$,/non-existent,
s,^:,,'
note that an empty PATH contains one entry: the current
directory. So you need to have PATH=/non-existent ifever you
remove all the entries. ("/usr/local/bin:" should be changed to
"" (the current directory), and "/usr/local/bin" to
"/some-inexistent-dir").
--
Stephane
perl -lne'print join ":", grep !m(/usr), split /:/'
Nope, won't do.
perl's split ignores the leading and trailing ":" so can't be
used to split $PATH that way. See also my comment about an empty
$PATH.
echo "/bin:/usr/bin:" |
perl -lne'print join ":", grep !m(/usr), split /:/'
gives "/bin", it removed the current dir.
echo "/usr/bin" |
perl -lne'print join ":", grep !m(/usr), split /:/'
gives "", it *adds* the current dir.
--
Stephane
$ echo "/bin:/usr/bin:" | perl -lne'print join ":", grep !m(/usr), split
/:/, $_, -1'
/bin:
> echo "/usr/bin" |
> perl -lne'print join ":", grep !m(/usr), split /:/'
>
> gives "", it *adds* the current dir.
Isn't "." the current directory?
"." is the "." dir in the current directory (which generally is
the same as the current directory). "" is the current directory.
"/bin" means search in /bin only.
"/bin:" means search in /bin and the current directory
execvp("foo"...), will do:
execve("/bin/foo"...);
execve("foo"...);
"/bin:." means search in /bin and "."
execvp("foo"...), will do:
execve("/bin/foo"...);
execve("./foo"...);
"" means search in the current directory. There's no way to
specify: don't even try searching, so the work around is to
include only non-existing directories in $PATH. If you unset
PATH, a default value of PATH will be used.
"." means an additional lookup and may fail on filesystems that
don't have a "." entry but is safer with regards to scripts for
which the option terminator has been forgotten on the shebang
line (#! /bin/sh instead of #! /bin/sh -).
--
Stephane
ruby -ne 'puts split(/:/).reject{|s|s =~ %r{/usr(/|$)}}.
join(":")'