我想通过echo $VARIABLE
命令获得的path列表进行循环。
例如:
echo $MANPATH
将会返回
/usr/lib:/usr/sfw/lib:/usr/info
这是三条不同的path,每条path都以冒号分隔。 我想循环每个path。 有没有办法做到这一点? 谢谢。
感谢所有答复到目前为止,看起来我实际上不需要循环。 我只需要一个方法来取出冒号,这样我就可以在这三条path上运行一个ls
命令。
你可以使用Bash的模式替换参数扩展来填充你的循环变量。 例如:
MANPATH=/usr/lib:/usr/sfw/lib:/usr/info # Replace colons with spaces to create list. for path in ${MANPATH//:/ }; do echo "$path" done
注意:不要将替换扩展放在引号中。 您希望来自MANPATH的扩展值被for循环解释为单独的单词,而不是单个字符串。
您可以设置内部字段分隔符:
( IFS=: for p in $MANPATH; do echo "$p" done )
我使用了一个子shell,所以IFS的变化并没有反映在我当前的shell中。
在Bash中这样做的规范方法是适当地使用内置read
:
IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH")
这是唯一可靠的解决方案:将完成你想要的:在分隔符上拆分字符串:
并且相对于空格,换行符和全角字符(如*
, [ ]
等)是安全的(不同于其他答案:它们是全部坏了)。
在这个命令之后,你将有一个数组path_array
,你可以循环它:
for p in "${path_array[@]}"; do printf '%s\n' "$p" done
通过这种方式,您可以安全地通过$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
你可以检查$IFS
的值,
IFS='xxxxxxxx' while IFS=: read -d: -r path; do echo "${IFS}${path}" done <<< "${PATH:+"${PATH}:"}"
和输出将是这样的事情。
xxxxxxxx/usr/local/bin xxxxxxxx/usr/bin xxxxxxxx/bin
参考StackExchange上的另一个问题 。
你可以在$ {}中使用Bash的X来实现这个功能:
for p in ${PATH//:/$'\n'} ; do echo $p; done
IFS=: arr=(${MANPATH}) for path in "${arr[@]}" ; do # <- quotes required echo $path done
…它确实照顾空间:o)但是如果你有这样的东西,也会添加空的元素:
:/usr/bin::/usr/lib:
…那么索引0,2将是空的(''),不能说为什么索引4没有设置
for p in $(echo $MANPATH | tr ":" " ") ;do echo $p done