Синтаксическая ошибка рядом с неожиданным токеном `('

15

Когда я использую код ниже в терминале SSH для CentOS, он работает нормально:

paste <(printf "%s\n" "TOP")

Но если я помещаю тот же строчный код в сценарий оболочки (test.sh) и запускаю сценарий оболочки из терминала, он выдаст ошибку, как это

./test.sh: line 30: syntax error near unexpected token ('   
./test.sh: line 30:     paste <(printf "%s\n" "TOP")

Как я могу решить эту проблему?

NecNecco
источник
Как именно ты это делаешь? что '#!' строка (если есть) запускает ваш скрипт? Похоже, вы вызываете интерпретатор оболочки, который не поддерживает этот синтаксис (например, dashвместо bash).
Стальдрайвер
У меня #!/bin/shнаверху. Я выполнил как, bash test.shно это тоже не сработало.
NecNecco
bashв режиме POSIX этот синтаксис также не поддерживается (при вызове с --posixили как /bin/sh). Использование #!/bin/bash.
Иордания
@NecNecco: У вас есть POSIXLY_CORRECTпеременная, установленная при запуске bash?
cuonglm
@jordanm переключение наверху решило #!/bin/bashпроблему.
NecNecco

Ответы:

23

Подстановка процессов не определен POSIX, поэтому не поддерживает все POSIX оболочки, только некоторые оболочки , как bash, zsh, ksh88, ksh93поддержка.

В Centosсистеме /bin/shесть символическая ссылка на /bin/bash. Когда bashвызывается с именем sh, bashпереходит в режим posix ( Bash Startup Files - вызывается с именем sh ). В режиме posix,process substitution не поддерживается, вызывает синтаксическую ошибку.

Скрипт должен работать, если вы звоните bashнапрямую bash test.sh. Если нет, возможно bash, перешел в режим posix. Это может произойти, если вы начинаете bashс --posixаргумента или переменная POSIXLY_CORRECTустановлена ​​при bashзапуске:

$ bash --posix test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")'

$ POSIXLY_CORRECT=1 bash test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")

Или bashпостроен с --enable-strict-posix-defaultопцией.

Здесь вам не нужно подменять процессы, вы можете использовать стандартные каналы оболочки:

printf "%s\n" "TOP" | paste -

-это стандартный способ сказать, pasteчтобы прочитать данные из стандартного ввода. В некоторых pasteреализациях вы можете опустить его, хотя это не стандартно.

Это было бы полезно при вставке вывода более чем одной команды, например:

paste <(cmd1) <(cmd2)

На системах, которые поддерживают /dev/fd/n, это можно сделать shс помощью:

{ cmd1 4<&- | { cmd2 3<&- | paste /dev/fd/3 -; } 3<&0 <&4 4<&-; } 4<&0

(это то, что <(...)делает внутренне).

cuonglm
источник
2

Вот еще один обходной путь. Вместо запуска команды запустите bash и передайте команду bash, используя -c:

bash -c 'paste <(printf "%s\n" "TOP")'
jgarbe
источник