Reputation: 9893
I'm trying to remove an entry in $PATH if that entry contains a given string foo
. For example PATH=/home/me/bin:/home/foo/bin:/usr/foo/bin:/bin
would become PATH=/home/me/bin:/bin
. I currently have
echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'
but this seems to be removing too many entries, even though I'm trying to use non-greedy matching. What am I doing wrong?
Upvotes: 0
Views: 104
Reputation: 35198
It's good of you to use non-greedy matching .*?
in your below regex.
echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'
However, there is a flaw in your regex because you did not limit the allowed characters, and therefore it can capture across your colon boundaries.
That's one reason why split
is a nice tool. It not only enforces boundaries but also the accepted characters between them.
It's of course possible to do this using a regex though, like you intended:
echo $PATH | perl -pe 's/[^:=]*foo[^:]*:?//g'
The above will leave a trailing colon if it's the last entry.
Upvotes: 0
Reputation: 289725
You can also use awk
to loop through the paths, printing just the ones that don't contain foo
:
awk -F: '{for (i=1; i<=NF; i++) if ($i !~ /foo/) {printf "%s%s", $i, (i==NF? RS : FS)}}'
-F:
sets :
as field separator.for (i=1; i<=NF; i++)
loop through the fields.if ($i !~ /foo/)
if the path does not contain the string foo
, then perform next action:printf "%s%s", $i, (i==NF? RS : FS)
print the line, ending with new line or :
depending on the position it is. If it is the last field, new line; otherwise, :
.$ cat a
/home/me/bin:/home/foo/bin:/usr/foo/bin:/bin
/home/me/bin:/home/fio/bin:/usr/foo/bin:/bin
$ awk -F: '{for (i=1; i<=NF; i++) if ($i !~ /foo/) {printf "%s%s", $i, (i==NF? RS : FS)}}' a
/home/me/bin:/bin
/home/me/bin:/home/fio/bin:/bin
Upvotes: 1
Reputation: 6355
I started to construct a regex that would deal with all the combinations of colons at either end, but it got complex fast. But since you're using Perl (good choice BTW) how about something like:
perl -e 'print join(":", grep { $_ !~ m/foo/ } split( ":", '"$PATH"' ) );'
Upvotes: 0
Reputation: 525
I would split the string, select the valid parts and then join the string again:
perl -e 'print join ":", grep !/foo/, split ":", $ENV{PATH}'
Upvotes: 5
Reputation: 785146
You can use:
perl -pe 's/:(.*?)foo[^:]*(?=:|$)//g' <<< "$PATH"
/home/me/bin:/bin
Upvotes: 1