You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZSH中FOR循环处理多行字符串的行为差异解析

三种Shell遍历写法的行为差异解析

1. 直接在for循环中使用命令替换

for CLOUD in $(jq -r '.clouds[].cloud_name' publicClouds.json)
do
 echo "> $CLOUD"
done

这种写法会逐个输出每个云服务商的名称,每个占一行。
原因很直白:Shell执行$(jq ...)拿到输出后,会自动按空格、换行、制表符(默认的IFS分隔符)拆分成独立片段,每个片段对应一个云名称。for循环会挨个遍历这些片段,所以每次循环只处理一个名称,输出符合预期。

2. 将结果存入普通变量后遍历

CLOUDS=$(jq -r '.clouds[].cloud_name' publicClouds.json)

for CLOUD in "$CLOUDS"
do
 echo "> $CLOUD"
done

这种写法会把所有云名称一次性输出在同一个>后面,换行只是变量里原本带的格式。

  • 普通变量CLOUDS存的是命令输出的完整内容,包括所有换行符,相当于把所有云名称“打包”成了一个整体字符串。
  • 用双引号"$CLOUDS"包裹变量时,Shell会原封不动地把这个“打包字符串”当作单个元素,for循环只会执行一次,自然一次性输出所有内容。
  • 要是去掉引号写for CLOUD in $CLOUDS,Shell会再次拆分字符串,看起来能正常遍历,但这是碰运气——如果某个云名称带空格(比如"AWS US East"),就会被拆成两个片段,遍历直接出错。

至于wc -l <<< $CLOUDS返回103,是因为<<<会把变量里的原始内容(包括所有换行符)传给wc -l,统计的就是变量内的总行数,证明换行符确实被完整保留了。

3. 将结果存入数组后遍历

CLOUDS=($(jq -r '.clouds[].cloud_name' publicClouds.json))
for CLOUD in $CLOUDS
do
 echo "> $CLOUD"
done

这种写法能正常逐个输出云名称,本质是用数组单独存储了每个名称。
CLOUDS=($(jq ...))会先把命令输出拆成片段,再把每个片段单独放进数组的一个位置——数组第1个元素对应第一个云名称,第2个元素对应第二个,以此类推。遍历的时候,$CLOUDS会展开数组所有元素,for循环就挨个处理。更稳妥的写法是for CLOUD in "${CLOUDS[@]}",这样就算云名称里有空格,也不会被错误拆分。

内容的提问来源于stack exchange,提问作者Brendan Stephens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 00:09:20