Мой друг спросил меня, почему эти два простых сценария не работают в обеих оболочках:
Тестовый файл «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
Может кто-нибудь объяснить мне, в чем разница?
Это - потому что Bash ведет себя по-другому когда $0
sh
.
От поведения Bash [Хакеры Bash Wiki]:
Режим SH
Когда Bash запускается в режиме совместимости SH, он пытается подражать поведению запуска исторических версий
sh
максимально тесно, при приспосабливании стандарту POSIX® также. Чтение файлов профиля/etc/profile
и~/.profile
, если это - оболочка входа в систему.Если это не оболочка входа в систему, ENV переменной среды оценен, и получающееся имя файла взято в качестве названия файла запуска.
После того, как файлы запуска читаются, Bash переходит к режиму совместимости POSIX(r) (для выполнения, не для запуска!).
Bash запускается в
sh
режим совместимости, когда:
- основное имя файла в
argv[0]
sh
(Внимание дорогие uber-умные пользователи Linux …/bin/sh
может быть связан с/bin/bash
, но это не означает, что действует как/bin/bash
)
Больше информации может быть найдено в Справочнике Bash: Bash Режим POSIX, конкретно:
- Замена процесса не доступна.
который является почему Ваш sh
сценарий перестал работать, как <(..)
синтаксис использует замену процесса.
Согласно
man bash
говорится
When invoked as sh, bash enters posix mode after the startup files are read.
Таким образом, вы не можете использовать функции bash при запуске скрипта с /bin/sh
.