【问题标题】:What is the most elegant way to remove a path from the $PATH variable in Bash?从 Bash 中的 $PATH 变量中删除路径的最优雅的方法是什么?
【发布时间】:2010-09-27 01:40:48
【问题描述】:

或者更一般地说,如何从 Bash 环境变量中以冒号分隔的列表中删除项目?

我以为我在几年前看到了一种简单的方法,使用更高级的 Bash 变量扩展形式,但如果是这样,我已经忘记了它。对 Google 的快速搜索结果出乎意料地少,而且没有一个我称之为“简单”或“优雅”的结果。比如分别使用sed和awk的两种方法:

PATH=$(echo $PATH | sed -e 's;:\?/home/user/bin;;' -e 's;/home/user/bin:\?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)

没有直接的东西存在吗?有什么类似于 Bash 中的 split() 函数吗?

更新:
看来我需要为我故意含糊的问题道歉;我对解决特定用例的兴趣不如对引发良好讨论的兴趣。幸运的是,我明白了!

这里有一些非常聪明的技巧。最后,我在我的工具箱中添加了以下三个功能。魔术发生在 path_remove 中,这主要是基于 Martin York 巧妙地使用awk 的 RS 变量。

path_append ()  { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }

唯一真正的麻烦是使用sed 删除尾随冒号。不过,考虑到 Martin 的其他解决方案是多么简单,我非常愿意接受它!


相关问题:How do I manipulate $PATH elements in shell scripts?

【问题讨论】:

  • 对于任何变量:WORK=`echo -n ${1} | awk -v RS=: -v ORS=: '$0 != "'${3}'"' | sed 's/:$//'`; eval "export ${2}=${WORK}" 但您必须将其称为func $VAR VAR pattern(基于@martin-york 和@andrew-aylett)

标签: bash shell path variable-expansion list-processing


【解决方案1】:

与@litb 一样,我为问题“How do I manipulate $PATH elements in shell scripts”提供了答案,所以我的主要答案就在那里。

bash 和其他 Bourne shell 衍生产品中的“拆分”功能最巧妙地是使用字段间分隔符 $IFS 实现的。例如,要将位置参数($1$2、...)设置为 PATH 的元素,请使用:

set -- $(IFS=":"; echo "$PATH")

只要 $PATH 中没有空格,它就可以正常工作。让它适用于包含空格的路径元素是一项重要的练习 - 留给感兴趣的读者。使用 Perl 等脚本语言处理它可能更简单。

我还有一个脚本 clnpath,我广泛使用它来设置我的 PATH。我在“How to keep from duplicating PATH variable in csh”的回答中记录了它。

【讨论】:

  • IFS=: a=( $PATH ); IFS= 拆分也不错。如果它们也包含空格,则可以使用。但是你得到了一个数组,并且不得不摆弄 for 循环等来删除名称。
  • 是的;它变得很复杂 - 就像我更新的评论一样,此时使用脚本语言可能更简单。
【解决方案2】:

我确实写了一个答案here(也使用 awk)。但我不确定这就是你要找的东西?它至少在我看来很清楚它的作用,而不是试图融入一行。不过,对于一个只删除东西的简单衬里,我建议

echo $PATH | tr ':' '\n' | awk '$0 != "/bin"' | paste -sd:

替换是

echo $PATH | tr ':' '\n' | 
    awk '$0 != "/bin"; $0 == "/bin" { print "/bar" }' | paste -sd:

或(较短但可读性较差)

echo $PATH | tr ':' '\n' | awk '$0 == "/bin" { print "/bar"; next } 1' | paste -sd:

无论如何,对于同样的问题,以及很多有用的答案,请参阅here

【讨论】:

  • 如果你想删除包含部分字符串的行,请使用awk '$0 !~ "/bin"'。 IE。使用 awk 运算符 !~ 保留不包含 '/bin' 的行。
【解决方案3】:

由于这往往会带来很大的问题,因为没有优雅的方式,我建议通过重新安排解决方案来避免问题:构建您的 PATH 而不是试图拆除它。

如果我知道你真正的问题背景,我可能会更具体。在此期间,我将使用软件构建作为上下文。

软件构建的一个常见问题是它在某些机器上中断,最终是由于某人如何配置他们的默认 shell(PATH 和其他环境变量)。优雅的解决方案是通过完全指定 shell 环境来使您的构建脚本免疫。对构建脚本进行编码以根据您控制的组装件设置 PATH 和其他环境变量,例如编译器、库、工具、组件等的位置。使每个可配置项成为您可以单独设置、验证和然后在您的脚本中适当使用。

例如,我从新雇主那里继承了一个基于 Maven 的、面向 WebLogic 的 Java 构建。构建脚本因脆弱而臭名昭著,我和另一位新员工花了三周时间(不是全职,只是到处,但仍然很多小时)让它在我们的机器上工作。一个重要的步骤是我控制了 PATH,以便我确切地知道正在调用哪个 Java、哪个 Maven 以及哪个 WebLogic。我创建了环境变量来指向这些工具中的每一个,然后我根据这些以及其他一些工具计算了 PATH。类似的技术驯服了其他可配置的设置,直到我们最终创建了一个可重现的构建。

顺便说一句,不要使用 Maven,Java 是可以的,只有在绝对需要它的集群时才购买 WebLogic(否则不需要,尤其是不需要它的专有特性)。

最好的祝愿。

【讨论】:

  • 有时您没有 root 访问权限,而您的管理员会管理您的 PATH。当然,您可以自己构建,但是每次您的管理员移动某些东西时,您都必须弄清楚他把它放在哪里。这违背了拥有管理员的目的。
【解决方案4】:

好吧,在 bash 中,因为它支持正则表达式,所以我会这样做:

PATH=${PATH/:\/home\/user\/bin/}

【讨论】:

  • 不是只有路径名扩展,不是正则表达式吗?
  • 虽然 bash 确实支持正则表达式(从 bash 3 开始),但这不是一个例子,这是一个变量替换。
  • 这是模式变量扩展,解决方案有几个问题。 1)它不会匹配第一个元素。 2) 它将匹配以“/home/user/bin”开头的任何内容,而不仅仅是“/home/user/bin”。 3)它需要转义特殊字符。充其量,我会说这是一个不完整的例子。
猜你喜欢
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
相关资源
最近更新 更多