Bash技术疑问:同一行设置IFS后echo为何不识别?两段代码为何不等效?
Bash 两个常见疑问的解答
1. 为啥同一行设置IFS后,echo没把它当回事?
咱们得先搞明白Bash处理单条命令行的顺序:当你敲出IFS=, echo $var这种一行命令时,Bash会先做参数展开、分词这些操作,然后才会创建子进程,把设置的IFS传给子进程里的echo命令。
举个实际例子:假设你之前定义了var="a,b,c",执行IFS=, echo $var的时候,Bash第一步就会把$var展开成a,b,c——这时候用的是原来的默认IFS(空格、制表符、换行),逗号根本不在默认IFS里,所以不会被当成分隔符。等这一步做完,才会设置IFS=,并启动echo进程,但echo拿到的已经是展开后的字符串了,它只是负责输出,根本不会再用IFS去处理参数。
如果想让IFS生效,得把变量展开和IFS设置放到不同的执行阶段,比如用分号分开成两个命令:IFS=,; echo $var,或者用子shell把整个逻辑包起来:(IFS=,; echo $var)——这两种方式里,IFS是在当前shell(或子shell)里先设置好,然后再展开$var,这时候才会用新的IFS来分词。
2. 为啥那两段代码不等价?
我猜你说的应该是类似这两组代码的差异:
- 代码A:
IFS=, echo $var - 代码B:
IFS=,; echo $var
核心区别就在于变量赋值的作用域和执行时机:
- 代码A里的
IFS=,是作为echo命令的临时环境变量存在的,只在echo进程运行期间有效,而且Bash在处理这行命令时,是先展开$var(用原来的IFS),再启动echo并传递这个临时IFS——所以$var的分词根本没用到新的IFS。 - 代码B里的分号把命令拆成了两个独立的步骤:先在当前shell里设置IFS=,,这时候这个IFS会成为当前shell的环境变量,然后再执行echo命令,这时候展开
$var就会用刚设置的新IFS来分词了。
再拓展一下,这种差异不止体现在IFS上,任何VAR=value command形式的命令,VAR都只会在command的进程环境里生效,当前shell不会保留这个值;而VAR=value; command则会在当前shell里设置VAR,后续的命令都能用到这个值。
内容的提问来源于stack exchange,提问作者silel
相关产品推荐
相关产品推荐

