使用 sed 匹配字符或行尾

使用 sed 匹配字符或行尾

尝试清理PYTHONPATH具有通用语法的变量:

/a/path:/another/path/:/one/more/path

我想删除所有以 开头的路径/mnt。首先尝试sed

sed 's,/mnt/[^:]\+:,,g' <<< $PYTHONPATH

它会删除所有以 开头/mnt/,后跟一个或多个除冒号之外的字符以及后续冒号字符的出现。

然而,对于以下示例,这将失败:

PYTHONPATH="/mnt/first/path:/mnt/second/path"

因为第二条路径没有以冒号结尾。我找不到比使用略有不同的条件运行另一次搜索更好的办法了:

sed 's,/mnt/[^:]\+:,,g;s,/mnt/.*$,,g' <<< $PYTHONPATH

/mnt/所以现在,在删除所有以冒号结尾的出现项之后,另一次运行将删除所有以字符串结尾开头和结尾的出现项(事实上,最多只有一个) 。

问题:

  1. 对于这个任务来说,这是一个可接受的解决方案吗?
  2. 是否存在上述解决方案会失败的特殊情况?
  3. 这里是否有单一搜索解决方案?只是好奇。

提前致谢!

答案1

正如 Argonauts 所指出的,您可以使用 OR 语句在一行中完成此操作。您不一定必须使用该-r选项,但sed命令会稍微复杂一些,因为您必须转义括号和竖线,如下所示:

sed 's,/mnt/[^:]\+\(:\|$\),,g' <<< "$PYTHONPATH"

请注意,在 bash 中引用变量是一种很好的做法。

答案2

您所拥有的还可以接受,但更简单、更懒惰的解决方法是:

只需创建一个新变量

NEWVAR="${PYTHONPATH}:"
sed 's,/mnt/[^:]\+:,,g' <<< $NEWVAR

假设您将其分配给一个变量,并希望再次修剪添加的冒号,则使用 bash 变量操作您可以执行以下操作:

newvar="${PYTHONPATH}:"
nomnt=$( sed 's,/mnt/[^:]\+:,,g' <<< $newvar )
nomnt=${nomnt%%:}
echo ${nomnt}

或者在所有 sed 中:

sed 's,/mnt/[^:]\+:,,g;s/:$//;' <<< "${PYTHONPATH}:"

答案3

您可以在 sed 中使用扩展正则表达式来简化一些事情:

sed -r 's,/mnt/[^:]+(:|$),,g' <<< $PYTHONPATH

表示-r使用扩展正则表达式,在本例中是 OR 语句(:|$),导致它在冒号或行尾结束模式匹配。

注意:在 OS X 和 BSD 版本的 sed 中,-E使用-r

虽然这可能非常明显,但是如果您尝试更新 PYTHONPATH 本身,则需要在删除 /mnt/* 条目后分配值:

export PYTHONPATH=$(sed -r 's,/mnt/[^:]+(:|$),,g' <<< $PYTHONPATH)

相关内容