Umschließen eines Befehls mit einfachen und doppelten Anführungszeichen für einen anderen Befehl

10

Ich habe kürzlich etwas über Uhr gelernt , habe aber Probleme, es mit relativ ausgefeilten Befehlen zum Laufen zu bringen.

Zum Beispiel möchte ich Sie bitten watch, zshalle drei Sekunden den folgenden Befehl auszuführen * :

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

Wie Sie sehen können, enthält die obige Zeile unter anderem einfache Anführungszeichen und doppelte Anführungszeichen.

Also habe ich versucht:

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

aber dann bekam ich:

Keine Übereinstimmungen für x in gefunden! @ # $ # ....; getan

Ich habe andere Kombinationen ohne Erfolg ausprobiert. Hier ist einer dieser Versuche:

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

was auch zu einem ähnlichen Fehler führt.

Irgendwelche Ideen, wie das funktioniert?


* Ich würde mich auch für Lösungen interessieren, an denen gearbeitet wirdbash

Amelio Vazquez-Reina
quelle

Antworten:

16

Allgemeiner Tipp: Wenn Sie zwei Verschachtelungsebenen haben, vermeiden Sie die Verwendung von einfachen Anführungszeichen im inneren Befehl und einfache Anführungszeichen um den äußeren Befehl.

Weiterer Tipp: nicht verwendet Backticks - `…` - Code auszuführen, verwenden Sie stattdessen $(…)um ihn herum. Dollar-Klammern sind so ziemlich DWIM ('Mach was ich meine'), wenn es um verschachtelte Anführungszeichen geht. Backquotes haben arkane, Shell-abhängige Regeln.

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

Wenn Sie einfache Anführungszeichen in einem Befehl in einfachen Anführungszeichen benötigen, können Sie verwenden '\''. Stellen Sie sich diese vier Zeichen als die Möglichkeit vor, ein einfaches Anführungszeichen in einfache Anführungszeichen zu setzen. Technisch gesehen ist dies jedoch so aufgebaut, dass die Zeichenfolge in einfachen Anführungszeichen beendet, ein wörtliches einfaches Anführungszeichen angehängt und eine neue Zeichenfolge in einfachen Anführungszeichen (die immer noch an das angehängt wird) angehängt wird aktuelles Wort).

In komplexeren Fällen zählen Sie entweder die Anführungszeichen sorgfältig oder definieren Sie temporäre Variablen.

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

Diese Antwort ist nicht spezifisch für zsh. Zsh bringt hier nichts Wichtiges. Sie können ein wenig Anführungszeichen sparen, da bei Befehlsersetzungen keine doppelten Anführungszeichen erforderlich sind. Manchmal gibt es Möglichkeiten, integrierte Funktionen anstelle externer Befehle zu verwenden, um den Anführungszeichenbedarf zu verringern. Die zugrunde liegenden Probleme sind jedoch dieselben wie in anderen Shells.

Oh, und übrigens, beachten Sie, watchdass Ihr Befehl in ausgeführt wird sh, nicht in zsh. Wenn Sie den Befehl in zsh ausführen möchten, müssen Sie ihn ausführen

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

auf Debian / Ubuntu und

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

(noch mehr zitieren!) woanders.

Gilles 'SO - hör auf böse zu sein'
quelle
Danke @ Gilles. Das war sehr hilfreich. Interessanterweise watchkommt nicht mit den -xnoch -cOptionen auf meinem Computer. Ich habe es online nachgeschlagen und keine Manpages gefunden, auf denen sie erwähnt werden. Was machen diese Optionen?
Amelio Vazquez-Reina
1
@intrpc -xweist watchan, den Befehl nicht über eine Shell zu übergeben. Ich habe gerade herausgefunden, dass dies spezifisch für Debian / Ubuntu ist, obwohl es nicht als solches angegeben ist. Das -cwird an zshnicht weitergegeben watch.
Gilles 'SO - hör auf böse zu sein'
@ Gilles Die -xund -execOptionen existieren beide in meinem watch(auf Gentoo), also ist dies definitiv nicht Debian-spezifisch. Vielleicht hast du mit einer anderen Version von verglichen watch? Meins kommt aus dem Procps- Paket.
Rozcietrzewiacz
1
@rozcietrzewiacz watchkommt auch von procpsDebian. Die offizielle Quelle hat nicht --exec. Das Paket in Debian (und Derivaten einschließlich Ubuntu) fügt die Option in einem Debian-spezifischen Patch hinzu ( watch_exec_beep.patches ist "Mortys Watch Exec Patch" aus Fehler # 410967 ). Gentoo hat möglicherweise einen ähnlichen Patch übernommen.
Gilles 'SO - hör auf böse zu sein'