Hace poco aprendí sobre el reloj, pero tengo problemas para hacerlo funcionar con comandos relativamente sofisticados.
Por ejemplo, me gustaría preguntarle a watch
para ejecutar el siguiente comando en zsh
cada tres segundos:
for x in `command_1 | grep keyword | cut -d' ' -f1`; do command_2 "word[word=number]" $x; done
como puede ver, la línea de arriba incluye comillas simples, comillas dobles, entre otros caracteres especiales.
Así que probé:
watch -n 3 "for x in `my_command | grep keyword | cut -d' ' -f1`; do command2 "rusage[mem=7000]" $x; done"
pero luego obtuve:
no se encontraron coincidencias para x en [email protected]#$# ….; hecho
Probé otras combinaciones sin éxito. Este es uno de esos intentos:
watch -n 3 "for x in $(bjobs -w | grep pre_seg | cut -d' ' -f1); do bmod -R "rusage[mem=7000]" $x; done"
lo que también da como resultado un error similar.
¿Alguna idea de cómo hacer que esto funcione?
También estaría interesado en soluciones que funcionen en bash
Respuesta aceptada:
Sugerencia general:si tiene dos niveles de anidamiento, evite usar comillas simples en el comando interno y use comillas simples alrededor del comando externo.
Consejo adicional:no uses acentos graves – `…`
– para ejecutar código, en su lugar use $(…)
alrededor. Los paréntesis en dólares son más o menos DWIM ('Haz lo que quiero decir') cuando se trata de comillas anidadas; las comillas inversas tienen reglas misteriosas que dependen del caparazón.
watch -n 3 'for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
Si necesita comillas simples dentro de un comando entre comillas simples, puede usar '''
. Piense en estos cuatro caracteres como la forma de citar una comilla simple dentro de comillas simples, aunque técnicamente hablando esto se construye como terminar la cadena entre comillas simples, agregar una comilla simple literal y comenzar una nueva cadena entre comillas simples (todavía adjunta a la palabra actual).
Para casos más complejos, cuente minuciosamente las comillas o defina variables temporales.
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 respuesta no es específica de zsh. Zsh no trae nada importante aquí. Puede ahorrarse un poco de comillas porque no hay necesidad de comillas dobles en las sustituciones de comandos y, a veces, hay formas de usar comandos integrados en lugar de externos que reducen las necesidades de comillas, pero los problemas subyacentes son los mismos que en otros shells.
Ah, y por cierto, ten en cuenta que watch
ejecutará su comando en sh
, no en zsh. Si desea ejecutar el comando en zsh, debe ejecutar
watch -n 3 -x zsh -c "$cmd"
en Debian/Ubuntu, y
export cmd
watch -n 3 'exec zsh -c "$cmd"'
(¡aún más citas!) en otro lugar.
Relacionado:¿Encerrar o no encerrar el valor de una variable entre comillas en bash?