【问题标题】:How can I delete a specific variable from my PATH environment variable using fish shell如何使用鱼壳从我的 PATH 环境变量中删除特定变量
【发布时间】:2016-09-28 17:39:22
【问题描述】:

给定一个输入变量,比如 usr/bin 和以下 PATH

 echo $PATH 
 /usr/local/bin /usr/bin /bin /usr/sbin /sbin /usr/local/sbin /Developer/bin

我如何编写(在鱼壳中)给定字符串/输入的函数可以从我的 PATH 变量中删除该路径? -> 理想情况下删除第一次出现的情况(与删除所有出现的此类变量的情况相比)

我正在考虑写一个小函数,比如

deleteFromPath usr/bin

用 Perl/python/ruby 这样的脚本语言而不是 fish shell 会更好吗?

for x in $list
    if [ $x = $argv ]
        //delete element x from list -> How?
    end
end

【问题讨论】:

  • 有什么原因让您跳到 perl/python/ruby 而不是 POSIX shell?
  • IFS=: read -r -a path_entries <<<"$PATH"; for idx in "${!path_entries[@]}"; do for arg; do [[ ${path_entries[$idx]} = "$arg" ]] && unset path_entries[$idx]; done; done; printf -v PATH '%s:' "${path_entries[@]}"; PATH=${PATH%':'} 让我印象深刻,它是对正确性持谨慎态度的 bash 实现相当理智。 fish 真的不是为编写脚本而构建的;它是一个非常交互式 shell。
  • @CharlesDuffy: fish 不支持POSIX 子串删除技术?
  • @Inian,fish 根本没有写成 POSIX shell。他们本可以借用任何给定的功能,但我不会花时间了解他们做了什么或没做什么。
  • @CharlesDuffy:干杯!只是想澄清一下,然后再使用相同的答案发布答案​​! :)

标签: shell scripting fish


【解决方案1】:

这在鱼中很容易做到。

使用set -e,您不仅可以删除整个变量,还可以删除列表中的元素,例如set -e PATH[2] 删除第二个元素(fish 从 1 开始计算列表索引)。

使用contains -i,您可以找到元素所在的索引。

所以你会想打电话给set -e PATH[(contains -i $argv $PATH)]

修复了一些错误处理和边缘情况,这看起来像

 function deleteFromPath
     # This only uses the first argument
     # if you want more, use a for-loop
     # Or you might want to error `if set -q argv[2]`
     # The "--" here is to protect from arguments or $PATH components that start with "-"
     set -l index (contains -i -- $argv[1] $PATH)
     # If the contains call fails, it returns nothing, so $index will have no elements
     # (all variables in fish are lists)
     if set -q index[1]
         set -e PATH[$index]
     else
         return 1
     end
  end

请注意,这会比较路径字符串,因此您需要调用deleteFromPath /usr/bin,并带有前导“/”。否则它不会找到组件。

【讨论】:

    【解决方案2】:

    我们可以调用 bash。 :)

    function removePathElements
        set PATH (bash -c 'IFS=: read -r -a path_entries <<<"$PATH"; for idx in "${!path_entries[@]}"; do for arg; do [[ ${path_entries[$idx]} = "$arg" ]] && unset path_entries[$idx]; done; done; printf "%s\n" "${path_entries[@]}"' _ $argv)
    end
    

    要清楚,这里嵌入的 bash 代码是:

    IFS=: read -r -a path_entries <<<"$PATH"
    for idx in "${!path_entries[@]}"; do
      for arg; do
        [[ ${path_entries[$idx]} = "$arg" ]] && unset path_entries[$idx]
      done
    done
    printf "%s\n" "${path_entries[@]}"
    

    【讨论】:

    • 要明确 - 这绝对不是一个很好的答案,鱼原生接受的答案值得被接受并得到我的支持。另一方面,AFAICT 关于这个没有任何,这就是为什么我将它留在原处(如果真的有 一个不正确的方面,而不是仅仅冗长和低效)。
    猜你喜欢
    • 2017-08-16
    • 2011-03-05
    • 2019-04-12
    • 2019-05-15
    • 2019-06-30
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多