NUMBERS='1,2,3 4,5,6 7,8,9'
for TOUPLE in $NUMBERS;
do IFS=',';
set -- $TOUPLE
echo \($1, $2, $3\)
done
echo ''
for TRIPLE in $NUMBERS;
do IFS=',';
set -- $TRIPLE
echo \($1, $2, $3\)
done
Run Code Online (Sandbox Code Playgroud)
这些应该基本上是相同的循环,并且它们应该打印相同的输出.但是,当我执行脚本时,我得到以下输出:
(1, 2, 3)
(4, 5, 6)
(7, 8, 9)
(1, , )
(2, , )
(3 4, , )
(5, , )
(6 7, , )
(8, , )
(9, , )
Run Code Online (Sandbox Code Playgroud)
为什么第二个循环的行为与第一个循环不同?
第一个循环具有for TOUPLE in $NUMBERS默认值$IFS- 数字在空白处分割.在循环内部,你会改变$IFS,这种变化是永久性的.它不仅会影响以下内容set -- $TOUPLE,还会影响脚本的其余部分.
当第二个for TRIPLE in $NUMBERS运行时,更改以$IFS防止$NUMBERS被正确分割.它用逗号分隔而不是空格.哎呀.
如果要将循环彼此隔离,确保它的最简单方法是将它们包装在括号中,以便它们在子shell中执行.子壳中的变量赋值不会影响父shell.
(
for TOUPLE in $NUMBERS; do
IFS=','
set -- $TOUPLE
echo "($1, $2, $3)"
done
)
echo
(
for TRIPLE in $NUMBERS; do
IFS=','
set -- $TRIPLE
echo "($1, $2, $3)"
done
)
Run Code Online (Sandbox Code Playgroud)
如果你切换set到a,read你可以$IFS暂时改变reads 的持续时间,并完全避免这种混乱.
for TUPLE in $NUMBERS; do
IFS=',' read a b c <<< "$TUPLE"
echo "($a, $b, $c)"
done
Run Code Online (Sandbox Code Playgroud)
我会更进一步,避免循环遍历字符串变量.数组更适合,不涉及任何字符串拆分.远离不带引号的变量扩展是一个好习惯.
tuples=(1,2,3 4,5,6 7,8,9)
for tuple in "${tuples[@]}"; do
IFS=',' read a b c <<< "$tuple"
echo "($a, $b, $c)"
done
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
285 次 |
| 最近记录: |