为什么 /bin/bash 脚本可以运行,而 /bin/sh 脚本却不运行?

为什么 /bin/bash 脚本可以运行,而 /bin/sh 脚本却不运行?

我的朋友问我为什么这两个简单的脚本在两个 shell 中都不起作用:

测试文件“abc.txt”:

aaa
111
bbb
111
ccc
111
ddd

脚本#1(a):

#!/bin/sh
while read -r line ; do
    echo "Processing $line"
done < <(grep 111 abc.txt)

输出:

./a: line 4: syntax error near unexpected token `<'
./a: line 4: `done < <(grep 111 abc.txt)'

脚本#2(b):

#!/bin/bash
while read -r line ; do
    echo "Processing $line"
done < <(grep 111 abc.txt)

输出:

Processing 111
Processing 111
Processing 111

我检查了我的计算机上的 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

有人能解释一下区别在哪里吗?

答案1

这是因为 Bash 在 时$0的行为有所不同sh

Bash 的行为 [Bash Hackers Wiki]

SH 模式

当 Bash 以 SH 兼容模式启动时,它会尝试尽可能地模仿历史版本的启动行为sh,同时符合 POSIX® 标准。如果是登录 shell,则读取的配置文件为/etc/profile和 。~/.profile

如果它不是登录 shell,则会评估环境变量 ENV,并将生成的文件名作为启动文件的名称。

读取启动文件后,Bash 进入POSIX(r) 兼容模式(用于运行,而不是用于启动!)

在以下情况下,Bash 会以sh兼容模式启动:

  • 中的基本文件名 argv[0]sh(请注意,聪明的 Linux 用户.../bin/sh可能链接到 /bin/bash,但这并不意味着它的作用类似于 /bin/bash

更多信息请访问Bash 参考手册:Bash POSIX 模式, 具体来说:

  • 无法进行进程替换。

这就是您的sh脚本失败的原因,因为<(..)语法使用了进程替换。

答案2

根据

man bash

它说

When invoked as sh, bash enters posix mode after the startup files are read.

因此,在使用 运行脚本时,您无法使用 bash 功能/bin/sh

相关内容