Błąd składni w pobliżu nieoczekiwanego tokena `('


15

Kiedy używam poniższego kodu w terminalu SSH dla CentOS, działa dobrze:

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

Ale jeśli umieszczę ten sam kod wiersza w skrypcie powłoki (test.sh) i uruchomię skrypt powłoki z terminala, zgłasza błąd, ponieważ

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

Jak mogę rozwiązać ten problem?


Jak dokładnie go uruchamiasz? co '#!' linia (jeśli istnieje) uruchamia skrypt? Wygląda na to, że wywołujesz interpreter powłoki, który nie obsługuje tej składni (np. dashZamiast bash).
steeldriver

Mam #!/bin/shna górze. Wykonałem jako, bash test.shale to też nie zadziałało.
NecNecco

bashw trybie POSIX też nie obsługuje tej składni (wywoływanej z --posixlub as /bin/sh). Zastosowanie #!/bin/bash.
jordanm

@NecNecco: Czy masz POSIXLY_CORRECTzmienną ustawioną podczas uruchamiania bash?
cuonglm

Przełączanie @jordanm #!/bin/bashna górze naprawiło problem.
NecNecco

Odpowiedzi:


23

Zmiana procesu nie POSIX, dlatego nie wszystkie powłoki POSIX wspiera się tylko niektóre, takie jak muszle bash, zsh, ksh88, ksh93wsparcie.

W Centossystemie /bin/shjest dowiązanie symboliczne do /bin/bash. Kiedy bashjest wywoływany z nazwą sh, bashprzechodzi w tryb posiksowy ( Bash Startup Files - wywoływany z nazwą sh ). W trybie POSIX process substitutionnie jest obsługiwany, powoduje błąd składniowy.

Skrypt powinien działać, jeśli zadzwonisz bashbezpośrednio bash test.sh. Jeśli nie, być może bashwszedł w tryb posiksowy. Może się to zdarzyć, jeśli zaczynasz bashod --posixargumentu lub zmienna POSIXLY_CORRECTjest ustawiona podczas bashuruchamiania:

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

Lub bashjest zbudowany z --enable-strict-posix-defaultopcją.

Tutaj nie potrzebujesz podstawiania procesów, możesz użyć standardowych potoków powłoki:

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

-to standardowy sposób pastena odczytanie danych ze standardowego wejścia. W przypadku niektórych pasteimplementacji można to pominąć, choć nie jest to standardowe.

Przydałoby się wkleić dane wyjściowe więcej niż jednego polecenia, np .:

paste <(cmd1) <(cmd2)

W systemach, które obsługują /dev/fd/n, można to zrobić za shpomocą:

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

(to, co <(...)robi wewnętrznie).


2

Oto kolejne obejście. Zamiast uruchomić polecenie, uruchom bash i przekaż polecenie bash, używając -c:

bash -c 'paste <(printf "%s\n" "TOP")'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.