Помилка синтаксису біля несподіваного маркера `('


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")

Як я можу виправити цю проблему?


Як саме ти це працюєш? що '#!' рядок (якщо такий є) починає ваш сценарій? Схоже, ви викликаєте інтерпретатора оболонки, який не підтримує цей синтаксис (наприклад, dashзамість bash).
steeldriver

Я маю #!/bin/shна вершині. Я виконав як, bash test.shале і це не спрацювало.
NecNecco

bashв режимі POSIX також не підтримує цей синтаксис (при виклику з --posixабо як /bin/sh). Використовуйте #!/bin/bash.
jordanm

@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 - викликається ім'ям 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читати дані зі stdin. У деяких pasteреалізаціях ви можете опустити це, хоча це не є стандартним.

Там, де було б корисно, це коли вставляти висновок більше однієї команди, як у:

paste <(cmd1) <(cmd2)

У системах, що підтримують /dev/fd/n, це можна зробити за shдопомогою:

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

(це те, що <(...)робить внутрішньо).


2

Ось ще один спосіб вирішення. Замість виконання команди, запустіть bash і передайте команду bash, використовуючи -c:

bash -c 'paste <(printf "%s\n" "TOP")'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.