2

我正在过滤PATH变量,以便删除某些元素(在下面的示例中,它是包含字符串的元素x86;实际上我正在寻找字符串site-packages):

$ echo $(IFS=:;arr=($PATH);echo "${arr[*]//*x86*}")
/usr/local/bin:/usr/bin:/cygdrive/c/Program Files/Common Files/Microsoft Shared/Windows Live::/cygdrive/c/Program Files/Lenovo Fingerprint Reader:::/cygdrive/c/Program Files/Intel/iCLS Client:/cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/IPT:::::/cygdrive/c/Program Files/Intel/WiFi/bin:/cygdrive/c/Program Files/Common Files/Intel/WirelessCommon:/cygdrive/c/Program Files/Common Files/Lenovo:::/cygdrive/c/SWTOOLS/ReadyApps:::::/usr/lib/lapack

这工作得很好,除了所有被清零的元素仍然在那里,但是是空的。我想最终消除这些元素,并且我不想使用 bash 以外的任何东西来做到这一点(我知道我可以使用tr,但出于可移植性的原因,我强烈希望使用仅 bash 的解决方案)。

这是基于 tr 的解决方案:

echo $(IFS=:;arr=($PATH);echo "${arr[*]//*x86*}" | tr -s :)

更新:我正在使用数组,因为我希望在路径元素中的空格(或冒号以外的任何其他内容)面前保持稳健。

4

4 回答 4

3

你必须更明确地说明它:

PATH=$(
  IFS=:
  new=()
  for p in $PATH; do
    [[ $p != *x86* ]] && new+=("$p")
  done
  echo "${new[*]}"
)

它更冗长,但根据要求正确且仅限 bash

于 2013-11-08T18:24:04.637 回答
2

这不需要显式循环,但可能有点脆弱。它使用退格来“取消写入”要删除的目录前面的冒号,如果删除了第一个或最后一个目录,则需要特殊处理PATH

echo $(IFS=:;
       arr=($PATH);
       # When finally echoed, any \b character will remove
       # the preceding colon from the output.
       new="${arr[*]//*x86*/$'\b'}";
       # Remove :\b if last directory was removed
       new=${new%:$'\b'};
       # Remove \b: if first directory was removed
       echo "${new#$'\b':}")
于 2013-11-08T19:03:19.490 回答
0

假设成分不包含空格,这应该与PATH空数组元素在arr2赋值时被丢弃

echo $(IFS=:;arr=($PATH);unset IFS;arr2=(${arr[@]//*x86*});IFS=:;echo "${arr2[*]}")
于 2013-11-08T19:11:10.010 回答
0

这是一个使用循环构建连续数组的版本:

$ echo $(IFS=:;arr=($PATH);sqarr="${arr[*]//*x86*}";declare -a finalarr; for item in $sqarr; do [[ $item ]] && finalarr+=("$item"); done; echo "${finalarr[*]}")
/usr/local/bin:/usr/bin:/cygdrive/c/Program Files/Common Files/Microsoft Shared/Windows Live:/cygdrive/c/Program Files/Lenovo Fingerprint Reader:/cygdrive/c/Program Files/Intel/iCLS Client:/cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/IPT:/cygdrive/c/Program Files/Intel/WiFi/bin:/cygdrive/c/Program Files/Common Files/Intel/WirelessCommon:/cygdrive/c/Program Files/Common Files/Lenovo:/cygdrive/c/SWTOOLS/ReadyApps:/usr/lib/lapack

跨多行:

$(
  IFS=:
  arr=($PATH)
  sqarr="${arr[*]//*x86*}"
  declare -a finalarr
  for item in $sqarr; do 
      [[ $item ]] && finalarr+=("$item")
  done 
  echo "${finalarr[*]}"
)
于 2013-11-08T18:31:46.853 回答