Avvolgimento di un comando che include virgolette singole e doppie per un altro comando


10

Di recente ho appreso di watch , ma ho problemi a farlo funzionare con comandi relativamente sofisticati.

Ad esempio, vorrei chiedere watchdi eseguire il seguente comando zshogni tre secondi * :

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

come puoi vedere la riga sopra include virgolette singole, virgolette doppie, tra gli altri caratteri speciali.

Quindi ho provato:

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

ma poi ho ottenuto:

nessuna corrispondenza trovata per x in! @ # $ # ....; fatto

Ho provato altre combinazioni senza successo. Ecco uno di quei tentativi:

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

che provoca anche un errore simile.

Qualche idea su come farlo funzionare?


* Sarei anche interessato a soluzioni che funzionanobash

Risposte:


16

Suggerimento generale: se hai due livelli di annidamento, evita di utilizzare virgolette singole nel comando interno e usa virgolette singole attorno al comando esterno.

Suggerimento aggiuntivo: non usare i backtick - `…` - per eseguire il codice, invece usalo $(…)attorno. Le parentesi in dollari sono praticamente DWIM ('Fai quello che voglio dire') quando si tratta di virgolette nidificate; i backquotes hanno regole arcane e dipendenti dalla shell.

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

Se sono necessarie virgolette singole all'interno di un comando a virgoletta singola, è possibile utilizzare '\''. Pensa a questi quattro caratteri come al modo di citare una singola virgoletta all'interno di virgolette singole, sebbene tecnicamente parlando sia costruita come fine della stringa a virgoletta singola, aggiungi una virgoletta singola letterale e inizia una nuova stringa a virgoletta singola (ancora aggiunta al parola corrente).

Per casi più complessi, contare scrupolosamente le virgolette o definire variabili temporanee.

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

Questa risposta non è specifica per zsh. Zsh non porta nulla di importante qui. È possibile risparmiare un po 'di preventivo perché non è necessario utilizzare virgolette doppie per le sostituzioni di comandi e, a volte, esistono modi per utilizzare i comandi integrati anziché i comandi esterni che riducono le esigenze di quotazione, ma i problemi sottostanti sono gli stessi di altre shell.

Oh, e comunque, nota che watcheseguirà il tuo comando in sh, non in zsh. Se si desidera eseguire il comando in zsh, è necessario eseguire

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

su Debian / Ubuntu e

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

(ancora più citando!) altrove.


Grazie @Gilles. È stato molto utile. È interessante notare che watchnon viene fornito con le opzioni -x-csulla mia macchina. L'ho cercato online e non ho trovato nessuna man page che li menzioni. Cosa fanno queste opzioni?
Amelio Vazquez-Reina,

1
@intrpc -xdice di watchnon passare il comando attraverso una shell. Ho appena scoperto che questo è specifico per Debian / Ubuntu, anche se non è indicato come tale. La -cviene passato zsh, per non watch.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Le opzioni -xe -execesistono entrambe nel mio watch(su gentoo), quindi questo non è specifico di Debian. Forse hai confrontato con qualche altra versione di watch? Il mio viene dal pacchetto procps .
rozcietrzewiacz,

1
@rozcietrzewiacz watchviene anche da procpsDebian. La fonte ufficiale non ha --exec. Il pacchetto in Debian (e derivati ​​incluso Ubuntu) aggiunge l'opzione in una patch specifica di Debian ( watch_exec_beep.patch; è "Mortys watch exec patch" dal bug # 410967 ). Gentoo potrebbe aver adottato una patch simile.
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.