繁体   English   中英

根据正则表达式删除$ PATH条目

[英]Remove $PATH entry based on regex

我正在尝试删除$ PATH中的条目,如果该条目包含给定的字符串foo 例如PATH=/home/me/bin:/home/foo/bin:/usr/foo/bin:/bin将成为PATH=/home/me/bin:/bin 我目前有

echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'

但这似乎删除了太多条目,即使我尝试使用非贪婪匹配也是如此。 我究竟做错了什么?

我将分割字符串,选择有效部分,然后再次加入字符串:

perl -e 'print join ":", grep !/foo/, split ":", $ENV{PATH}'

您可以使用:

perl -pe 's/:(.*?)foo[^:]*(?=:|$)//g' <<< "$PATH"
/home/me/bin:/bin

您还可以使用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

我开始构建一个正则表达式,它可以处理任一端的​​所有冒号组合,但是它变得很快。 但是由于您使用的是Perl(顺便说一句,顺便说一句),像这样的事情如何:

perl -e 'print join(":", grep { $_ !~ m/foo/ } split( ":", '"$PATH"' ) );'

使用非贪婪匹配.*?对您有好处.*? 在下面的正则表达式中。

echo $PATH | perl -pe 's/:(.*?)foo(.*?):/:/g'

但是,您的正则表达式存在缺陷,因为您没有限制允许的字符,因此可以跨越冒号边界捕获。

这就是为什么split是一个很好的工具的原因。 它不仅强制执行边界,还强制执行边界之间的可接受字符。

当然,可以使用正则表达式来执行此操作,就像您想要的那样:

echo $PATH | perl -pe 's/[^:=]*foo[^:]*:?//g'

如果是最后一个条目,则上面将留下一个冒号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM