如果该条目包含给定字符串foo
,我正在尝试删除$ PATH中的条目。例如,PATH=/home/me/bin:/home/foo/bin:/usr/foo/bin:/bin
将成为PATH=/home/me/bin:/bin
。我目前有
echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'
但这似乎删除了太多条目,即使我正在尝试使用非贪婪的匹配。我做错了什么?
答案 0 :(得分:5)
我会分割字符串,选择有效部分,然后再次加入字符串:
perl -e 'print join ":", grep !/foo/, split ":", $ENV{PATH}'
答案 1 :(得分:1)
您可以使用:
perl -pe 's/:(.*?)foo[^:]*(?=:|$)//g' <<< "$PATH"
/home/me/bin:/bin
答案 2 :(得分:1)
您还可以使用awk
遍历路径,只打印不包含foo
的路径:
awk -F: '{for (i=1; i<=NF; i++) if ($i !~ /foo/) {printf "%s%s", $i, (i==NF? RS : FS)}}'
-F:
将:
设置为字段分隔符。for (i=1; i<=NF; i++)
遍历字段。if ($i !~ /foo/)
如果路径不包含字符串foo
,请执行下一步操作:printf "%s%s", $i, (i==NF? RS : FS)
打印该行,以新行或:
结尾,具体取决于其位置。如果是最后一个字段,新行;否则,:
。$ 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
答案 3 :(得分:0)
我开始构建一个正则表达式,它可以处理两端冒号的所有组合,但速度很快。但是既然你正在使用Perl(很好的选择BTW),那就是:
perl -e 'print join(":", grep { $_ !~ m/foo/ } split( ":", '"$PATH"' ) );'
答案 4 :(得分:0)
您可以在下面的正则表达式中使用非贪婪的匹配.*?
。
echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'
但是,正则表达式中存在一个缺陷,因为您没有限制允许的字符,因此它可以捕获整个冒号边界。
split
是一个很好的工具的原因之一。它不仅强制执行边界,还强制它们之间接受的字符。
当然,使用正则表达式可以做到这一点,就像你想要的那样:
echo $PATH | perl -pe 's/[^:=]*foo[^:]*:?//g'
如果它是最后一个条目,则上面会留下一个尾随冒号。