循环遍历Bash中路径变量的元素

tim*_*ran 30 linux bash

我想循环一个我从echo $VARIABLE命令中获得的路径列表.

例如:

echo $MANPATH 将返回

/usr/lib:/usr/sfw/lib:/usr/info

这是三条不同的路径,每条路径用冒号分隔.我想循环每个路径.有没有办法做到这一点?谢谢.

感谢到目前为止的所有回复,看起来我实际上根本不需要循环.我只需要一种取出冒号的方法,这样我就可以ls在这三条路径上运行一个命令.

cho*_*oba 49

您可以设置内部字段分隔符:

( IFS=:
  for p in $MANPATH; do
      echo "$p"
  done
)
Run Code Online (Sandbox Code Playgroud)

我使用了子shell,因此IFS中的更改不会反映在我当前的shell中.

  • 我相信这是有效的,即使$ MANPATH包含空格. (7认同)
  • 是! 这是唯一一个与包含空格(或者系统中的IFS)的路径一致的答案.在Cygwin,Fedora,Ubuntu上测试过,并在$ PATH上为我工作 (3认同)
  • 子 shell 不允许您返回任何结果变量! (2认同)

Tod*_*obs 17

您可以使用Bash的模式替换参数扩展来填充循环变量.例如:

MANPATH=/usr/lib:/usr/sfw/lib:/usr/info

# Replace colons with spaces to create list.
for path in ${MANPATH//:/ }; do
    echo "$path"
done
Run Code Online (Sandbox Code Playgroud)

注意:请勿将替换扩展括在引号中.您希望MANPATH中的扩展值被for循环解释为单独的单词,而不是单个字符串.

  • 据我所知,当任何子字符串包含空格时,这不起作用,这正是$ PATH使用非空格分隔符的原因.@ choroba的答案在这方面是正确的. (9认同)
  • 如果它们包含空格怎么办? (8认同)
  • @CodeGnome:问题一般是关于冒号分隔的列表,不一定是`$ MANPATH`.因此,您的评论是无意义的,并且您的答案仍然是错误的,因为它打破了有效输入. (8认同)
  • @intelfx:问题被标记为 [tag:linux]。如果你在 Linux 上的 *MANPATH* 中有空格,那么你在 Linux 上做错了。QED (2认同)

gni*_*urf 13

在Bash中执行此操作的规范方法是read适当地使用内置函数:

IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH")
Run Code Online (Sandbox Code Playgroud)

这是唯一可靠的解决方案:将不正是你想要什么:分裂的分隔字符串:和安全相对于空格,换行,像水珠字符*,[ ]等(不像其他的答案:他们都打破).

在这个命令之后,你将有一个数组path_array,你可以循环它:

for p in "${path_array[@]}"; do
    printf '%s\n' "$p"
done
Run Code Online (Sandbox Code Playgroud)


Yi *_* H. 5

这样,您可以安全地完成$PATH一个循环,而$IFS在循环内或循环外保持相同。

while IFS=: read -d: -r path; do # `$IFS` is only set for the `read` command
    echo $path
done <<< "${PATH:+"${PATH}:"}"   # append an extra ':' if `$PATH` is set
Run Code Online (Sandbox Code Playgroud)

您可以检查的值$IFS

IFS='xxxxxxxx'
while IFS=: read -d: -r path; do
    echo "${IFS}${path}"
done <<< "${PATH:+"${PATH}:"}"
Run Code Online (Sandbox Code Playgroud)

输出将是这样的。

xxxxxxxx/usr/local/bin
xxxxxxxx/usr/bin
xxxxxxxx/bin
Run Code Online (Sandbox Code Playgroud)

参考关于StackExchange的另一个问题