Envolvendo um comando que inclui aspas simples e duplas para outro comando

9

Eu recentemente aprendi sobre assistir , mas estou tendo problemas para fazê-lo funcionar com comandos relativamente sofisticados.

Por exemplo, gostaria de pedir ao watch para executar o seguinte comando em zsh a cada três segundos * :

for x in 'command_1 | grep keyword | cut -d' ' -f1'; do command_2 "word[word=number]" $x; done

como você pode ver, a linha acima inclui aspas simples, aspas duplas, entre outros caracteres especiais.

Então eu tentei:

watch -n 3 "for x in 'my_command | grep keyword | cut -d' ' -f1'; do command2 "rusage[mem=7000]" $x; done"

mas então eu peguei:

no matches found for x in !@#$# ....; done

Eu tentei outras combinações sem sucesso. Aqui está uma dessas tentativas:

watch -n 3 "for x in $(bjobs -w | grep pre_seg | cut -d' ' -f1); do bmod -R "rusage[mem=7000]" $x; done"

que também resulta em um erro semelhante.

Alguma idéia de como fazer isso funcionar?

* Eu também seria intersted em soluções que funcionam em bash

    
por Amelio Vazquez-Reina 26.10.2011 / 22:04

1 resposta

16

Dica geral: se você tiver dois níveis de aninhamento, evite usar aspas simples no comando interno e use aspas simples ao redor do comando externo.

Dica adicional: não use backticks - '…' - para executar código, em vez disso, use $(…) em torno dele. Parênteses do dólar é praticamente DWIM ("Faça o que eu quero dizer") quando se trata de citações aninhadas; os backquotes têm regras arcanas dependentes do shell.

watch -n 3 'for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'

Se você precisar de aspas simples dentro de um comando entre aspas simples, poderá usar '\'' . Pense nesses quatro caracteres como a maneira de citar uma aspa simples entre aspas simples, embora, tecnicamente falando, isso seja construído como finalizar a cadeia entre aspas simples, acrescentar uma aspa simples literal e iniciar uma nova cadeia de aspas simples (ainda anexada à palavra atual).

Para casos mais complexos, conte cuidadosamente as cotações ou defina variáveis temporárias.

cmd='for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
watch_cmd='watch -n 3 "$cmd"'

Esta resposta não é específica para zsh. Zsh não traz nada de importante aqui. Você pode economizar um pouco de cotação porque não há necessidade de aspas duplas em torno de substituições de comandos e, às vezes, há maneiras de usar built-ins em vez de comandos externos que reduzem as necessidades de cotação, mas os problemas subjacentes são os mesmos de outros shells.

Ah, e a propósito, observe que watch executará seu comando em sh , não em zsh. Se você quer executar o comando em zsh, você precisa rodar

watch -n 3 -x zsh -c "$cmd"

no Debian / Ubuntu e

export cmd
watch -n 3 'exec zsh -c "$cmd"'

(ainda mais citando!) em outro lugar.

    
por 26.10.2011 / 22:15