Por que a seqüência é importante na execução desses comandos bash?

10

Parece haver alguma inconsistência que não consigo entender em relação ao shell bash.

Se eu executar:

ls;date;time

os resultados das três perguntas são mostrados em seqüência.

No entanto, na troca de data e hora, aparece uma mensagem de erro.

Então, se eu executar:

ls;time;date

a mensagem de erro diz: bash: syntax error near unexpected token 'date' .

Alguém pode explicar isso?

    
por rohitvijaysharma 06.03.2013 / 06:50

2 respostas

10

O comando time em seu pipeline não é o binário /usr/bin/time , mas o bash time integrado. Compare man time com help time . O erro que você vê é que o bash não consegue analisar o argumento de time . Isso deve estar presente ou ser uma nova linha. É uma nova linha no seu primeiro exemplo, mas ausente no segundo.

Por outro lado, se você fosse executar

ls;date;'time'

ou

ls;'time';date

onde as aspas em torno de 'time' revogam seu status como uma palavra reservada, então o bash não tem problemas em analisar a linha. Agora, ele analisa três comandos em uma lista, que será executada em sequência, e /usr/bin/time relatará um erro de uso em ambos os casos.

Adendo

Observou-se que, embora time ; date produza um erro, time ; ; date não. A explicação provável é que time ; é interpretado por bash como equivalente a time <newline> . A expressão time ; ; date é então analisada como a lista de time ; e date .

Isso é consistente com a observação de que time ; e time ; ; são legais também, sendo o segundo analisado como a lista única contendo time ; seguido do ponto-e-vírgula opcional permitido após as listas.

Portanto, outra maneira de explicar por que time ; date gera o erro bash: syntax error near unexpected token 'date' é que time consome o ponto-e-vírgula separando-o de date . Só pode fazer isso porque time é uma palavra reservada.

    
por zwets 06.03.2013 / 07:47
2

O Bash trata o time incorporado como um caso especial, ao analisar as linhas de comando.

Como pode ser lido no bash manpage, a linha digitada é primeiro dividida em uma lista:

pipeline ; pipeline

onde um pipeline é:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

ou no nosso caso, simplesmente:

time command

i.e. Se a hora estiver presente, o comando must também estará presente.

[Há um caso especial que permite que time seja seguido por uma nova linha, mas isso não se aplica aqui]

Então, no nosso caso, temos:

time;date

sendo dividido em dois pipelines:

1. time
2. date

e o pipeline 1 não está bem formado, pois temos time sem um comando. Daí o erro.

Note que a linha de comando time também não funciona aqui:

$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]

bash analisa isso como esperado, em dois pipelines:

1. /usr/bin/time
2. date

e /usr/bin/time , em seguida, se recusam a executar sem argumento. Note que este é um erro de /usr/bin/time não um erro do bash.

A razão para o back-tick funcionar é que o back-tick impede que time seja interpretado como um elemento especial dentro do pipeline.

i.e. com o back-tick:

'time';date

é analisado como dois pipelines:

1. 'time'
2. date

Lembre-se de que um canal, no nosso caso, é:

[time] command

e o problema inicialmente foi que tínhamos time sem comando, o que não é permitido. Mas agora nós simplesmente temos o comando:

'time'

sem o time precedente, uma vez que os sinais de retorno significam que time é interpretado como o comando, não como uma palavra anterior.

Então, o bash executa seu coinde de% coin com% sem argumentos, o que é aceito. Não produz saída e não vemos erro.

Observe que:

'time'

na verdade, executa o resultado do time interno, ou seja, ele é executado independentemente do que o time incorporado produz no stdout. Mas como time por si só não escreve nada no stdout, parece funcionar.

Por fim, foi observado que isso funciona:

time ; ; date

que eu não posso explicar, infelizmente:)

    
por cdmackay 07.03.2013 / 20:39

Tags