Erro de sintaxe próximo ao token inesperado `('

15

Quando uso o código abaixo no terminal SSH do CentOS, ele funciona bem:

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

Mas se eu colocar o mesmo código de linha em um script de shell (test.sh) e executar o script de shell do terminal, ele emitirá um erro, pois

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

Como posso resolver este problema?

NecNecco
fonte
Como exatamente você está executando? o que '#!' linha (se houver) inicia seu script? Parece que você está chamando um interpretador de shell que não suporta essa sintaxe (por exemplo, em dashvez de bash).
Steeldriver
Eu tenho #!/bin/shno topo. Eu executei como bash test.shmas também não funcionou.
NecNecco
bashno modo POSIX também não suporta essa sintaxe (quando chamado com --posixou como /bin/sh). Use #!/bin/bash.
Jordanm
@NecNecco: Você tem POSIXLY_CORRECTvariáveis ​​definidas quando inicia bash?
precisa saber é
@ jordanm mudar para #!/bin/basho topo corrigiu o problema.
NecNecco

Respostas:

23

Substituição processo não é especificado por POSIX, por isso nem todos POSIX shell apoiá-lo, apenas alguns escudos como bash, zsh, ksh88, ksh93apoio.

No Centossistema, /bin/shé um link simbólico para /bin/bash. Quando bashé chamado com o nome sh, bashentra no modo posix ( arquivos de inicialização do Bash - chamado com o nome sh ). No modo posix, process substitutionnão é suportado, causa erro de sintaxe.

Script deve funcionar, se você ligar bashdiretamente bash test.sh. Caso contrário, talvez bashtenha entrado no modo posix. Isso pode ocorrer se você começar bashcom --posixargumento ou variável POSIXLY_CORRECTestiver definida quando bashiniciar:

$ 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 bashé construído com --enable-strict-posix-defaultopção.

Aqui, você não precisa de substituição de processo, pode usar tubos de shell padrão:

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

-é a maneira padrão de dizer pastepara ler os dados do stdin. Em algumas pasteimplementações, você pode omitir, embora isso não seja padrão.

Onde seria útil ao colar a saída de mais de um comando, como em:

paste <(cmd1) <(cmd2)

Em sistemas compatíveis /dev/fd/n, isso pode ser feito shcom:

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

(é o que <(...)faz internamente).

cuonglm
fonte
2

Aqui está outra solução alternativa. Em vez de executar o comando, execute bash e passe o comando para bash usando -c:

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