Erreur de syntaxe près du jeton inattendu `('

15

Lorsque j'utilise le code ci-dessous dans le terminal SSH pour CentOS, cela fonctionne bien:

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

Mais si je place le même code de ligne dans un script shell (test.sh) et que j'exécute un script shell à partir du terminal, cela génère une erreur comme ceci

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

Comment puis-je résoudre ce problème?

NecNecco
la source
Comment l' exécutez-vous exactement ? quoi '#!' ligne (le cas échéant) démarre votre script? Il semble que vous invoquiez un interpréteur de shell qui ne prend pas en charge cette syntaxe (par exemple dashau lieu de bash).
steeldriver
J'ai #!/bin/shau sommet. J'ai exécuté comme bash test.shmais ça n'a pas marché non plus.
NecNecco
bashen mode POSIX ne prend pas en charge cette syntaxe non plus (lorsqu'elle est appelée avec --posixou en tant que /bin/sh). Utilisez #!/bin/bash.
jordanm
@NecNecco: Avez-vous POSIXLY_CORRECTdéfini des variables lorsque vous démarrez bash?
cuonglm
@jordanm basculer en #!/bin/bashhaut a résolu le problème.
NecNecco

Réponses:

23

La substitution de processus n'est pas spécifié par POSIX, donc pas tous POSIX le soutenir, seuls quelques coquilles comme bash, zsh, ksh88, ksh93soutien.

Dans le Centossystème, /bin/shest un lien symbolique vers /bin/bash. Lorsque bashest invoqué avec un nom sh, bashpasse en mode posix ( Bash Startup Files - Appelé avec un nom sh ). En mode posix, process substitutionn'est pas pris en charge, provoque une erreur de syntaxe.

Le script devrait fonctionner, si vous appelez bashdirectement bash test.sh. Sinon, il bashest peut-être entré en mode posix. Cela peut se produire si vous commencez bashavec un --posixargument ou une variable POSIXLY_CORRECTdéfinie au bashdémarrage:

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

Ou bashest construit avec --enable-strict-posix-defaultoption.

Ici, vous n'avez pas besoin de substitution de processus, vous pouvez utiliser des tubes shell standard:

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

-est le moyen standard de dire pastede lire les données de stdin. Avec certaines pasteimplémentations, vous pouvez l'omettre bien que ce ne soit pas standard.

Il serait utile de coller la sortie de plusieurs commandes comme dans:

paste <(cmd1) <(cmd2)

Sur les systèmes qui prennent en charge /dev/fd/n, cela peut être fait shavec:

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

(c'est ce qui <(...)fait en interne).

cuonglm
la source
2

Voici une autre solution de contournement. Au lieu d'exécuter la commande, exécutez bash et passez la commande à bash en utilisant -c:

bash -c 'paste <(printf "%s\n" "TOP")'
jgarbe
la source