我的朋友问我为什么这两个简单的脚本在两个 shell 中都不起作用:
测试文件“abc.txt”:
aaa
111
bbb
111
ccc
111
ddd
Run Code Online (Sandbox Code Playgroud)
脚本#1 (a):
#!/bin/sh
while read -r line ; do
echo "Processing $line"
done < <(grep 111 abc.txt)
Run Code Online (Sandbox Code Playgroud)
输出:
./a: line 4: syntax error near unexpected token `<'
./a: line 4: `done < <(grep 111 abc.txt)'
Run Code Online (Sandbox Code Playgroud)
脚本#2 (b):
#!/bin/bash
while read -r line ; do
echo "Processing $line"
done < <(grep 111 abc.txt)
Run Code Online (Sandbox Code Playgroud)
输出:
Processing 111
Processing 111
Processing 111
Run Code Online (Sandbox Code Playgroud)
我在我的机器上检查了 bash 和 sh,如果我理解正确,这是同一回事。
/bin/sh 只是指向 /bin/bash 的链接:
-rwxr-xr-x 1 root root 938736 May 10 2012 bash
lrwxrwxrwx. 1 root root 4 Feb 13 10:20 sh -> bash
Run Code Online (Sandbox Code Playgroud)
有人可以解释我的区别在哪里吗?
这是因为 Bash 在$0is时表现不同sh。
来自Bash 的行为 [Bash Hackers Wiki]:
SH模式
当 Bash 在 SH 兼容模式下启动时,它会尝试尽可能模仿历史版本的启动行为
sh,同时也符合 POSIX® 标准。读取的配置文件是/etc/profileand~/.profile,如果它是登录 shell。如果它不是登录 shell,则评估环境变量 ENV 并将生成的文件名作为启动文件的名称。
读取启动文件后,Bash 进入POSIX(r) 兼容模式(用于运行,而不是用于启动!)。
Bash 在以下情况
sh下以兼容模式启动:
- 中的基本文件名
argv[0]是sh(注意亲爱的超级聪明的 Linux 用户....../bin/sh可能链接到/bin/bash,但这并不意味着它的作用像/bin/bash)
更多信息可以在Bash 参考手册:Bash POSIX Mode 中找到,特别是:
- 进程替换不可用。
这就是您的sh脚本失败的原因,因为<(..)语法使用了进程替换。