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

14

Quando eu uso o código abaixo no terminal SSH para o 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 shell script do terminal, ele lançará um erro como este

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

Como posso resolver este problema?

    
por NecNecco 24.08.2014 / 16:24

2 respostas

22

A substituição do processo não é especificada pelo POSIX, então nem todos os shell POSIX suportam, apenas alguns shells como bash , zsh , ksh88 , ksh93 support.

Em Centos system, /bin/sh é um link simbólico para /bin/bash . Quando bash é invocado com o nome sh , bash entra no modo posix ( Arquivos de Inicialização Bash - Invocados com o nome sh ). No modo posix, process substitution não é suportado, causa erro de sintaxe.

O script deve funcionar se você chamar bash diretamente bash test.sh . Se não, talvez bash tenha entrado no modo posix. Isso pode ocorrer se você iniciar bash com --posix argumento ou variável POSIXLY_CORRECT definida quando bash iniciar:

$ 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 é criado com a opção --enable-strict-posix-default .

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

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

- é a maneira padrão de informar paste para ler os dados do stdin. Com algumas implementações de paste , você pode omiti-lo embora não seja o padrão.

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

paste <(cmd1) <(cmd2)

Em sistemas que suportam /dev/fd/n , isso pode ser feito em sh com:

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

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

    
por 24.08.2014 / 18:09
2

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

bash -c 'paste <(printf "%s\n" "TOP")'
    
por 10.09.2015 / 15:45

Tags