为何/bin/sh脚本中通过管道的read命令无法正常工作?
为什么/bin/sh里read通过管道读取变量会失效?
核心原因:/bin/sh的管道子shell机制
在/bin/sh(大多是Dash这类Bourne兼容壳)里,管道|两边的命令都会跑在独立的子shell里。你写的echo AAA BBB | read X Y中,read是在管道右侧的子shell中执行的,它读出来的X和Y只属于这个子shell的环境。等子shell跑完退出,这些变量就跟着销毁了,父shell(脚本主进程)根本拿不到,所以后面echo $X输出空。
Zsh为什么能正常工作?
Zsh默认对管道的最后一个命令做了优化——它不会给最后一个命令新开子shell,而是直接在当前shell进程里执行。这样read读到的变量就留在当前环境里,后续自然能正常输出。
/bin/sh下的可行替代方案
如果要在/bin/sh里实现从命令输出读变量到当前shell,试试这几种方法:
Here文档+命令替换:
#!/bin/sh read X Y <<EOF $(echo AAA BBB) EOF echo $Xeval配合awk(注意:仅当输出内容完全可控时用,避免注入风险):
#!/bin/sh eval $(echo AAA BBB | awk '{print "X="$1"; Y="$2}') echo $X文件描述器重定向:
#!/bin/sh exec 3< <(echo AAA BBB) read X Y <&3 exec 3<&- echo $X
内容的提问来源于stack exchange,提问作者Martin Vegter
相关产品推荐
相关产品推荐

