Перенос команды, включающей одинарные и двойные кавычки для другой команды

10

Недавно я узнал о часах , но у меня возникли проблемы с его настройкой с помощью довольно сложных команд.

Например, я хотел бы попросить watchзапускать следующую команду zshкаждые три секунды * :

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

как вы можете видеть, строка выше включает одинарные кавычки, двойные кавычки и другие специальные символы.

Итак, я попробовал:

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

но потом я получил:

не найдено совпадений для x в! @ # $ # ....; сделанный

Я пробовал другие комбинации без успеха. Вот одна из тех попыток:

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

что также приводит к аналогичной ошибке.

Есть идеи, как сделать эту работу?


* Я также был бы заинтересован в решениях, которые работают наbash

Амелио Васкес-Рейна
источник

Ответы:

16

Общий совет: если у вас есть два уровня вложенности, избегайте использования одинарных кавычек во внутренней команде и используйте одинарные кавычки вокруг внешней команды.

Дополнительный совет: не используйте backticks - `…` для выполнения кода, вместо этого используйте $(…)его. Долларовые скобки - это в значительной степени DWIM («делай, что я имею в виду»), когда речь идет о вложенных кавычках; обратные кавычки имеют загадочные, зависящие от оболочки правила.

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

Если вам нужны одинарные кавычки внутри одинарных кавычек, вы можете использовать '\''. Думайте об этих четырех символах как о способе заключить одинарную кавычку в одинарные кавычки, хотя технически это выражается как конец строки в одинарных кавычках, добавление буквальных одинарных кавычек и начало новой строки в одинарных кавычках (все еще добавляется к текущее слово).

Для более сложных случаев либо тщательно подсчитывайте кавычки, либо определяйте временные переменные.

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

Этот ответ не является специфичным для Zsh. Зш не приносит здесь ничего особенного. Вы можете сэкономить немного цитирования, потому что нет необходимости в двойных кавычках при замене команд, и иногда есть способы использовать встроенные модули, а не внешние команды, которые уменьшают потребность в цитировании, но основные проблемы те же, что и в других оболочках.

Да, и, кстати, обратите внимание, что watchваши команды будут выполняться shв zsh. Если вы хотите выполнить команду в zsh, вам нужно запустить

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

в Debian / Ubuntu и

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

(еще больше цитируя!) в другом месте.

Жиль "ТАК - перестань быть злым"
источник
Спасибо, Жиль. Это было очень полезно. Интересно, watchчто не входит -xни с -cпараметрами на моей машине. Я посмотрел его в Интернете и не нашел ни одной справочной страницы, в которой бы они упоминались. Что делают эти опции?
Амелио Васкес-Рейна
1
@intrpc -xговорит watchне передавать команду через оболочку. Я только что узнал, что это специфично для Debian / Ubuntu, хотя это не указано как таковое. -cПередается zsh, не watch.
Жиль "ТАК - перестань быть злым"
@Gilles И параметры, -xи -execопции существуют в моем watch(на gentoo), так что это определенно не специфично для Debian. Может быть, вы сравнили с какой-то другой версией watch? Моя приходит из пакета procps .
rozcietrzewiacz
1
@rozcietrzewiacz watchпроисходит от procpsна Debian тоже. Официальный источник не имеет --exec. Пакет в Debian (и производных, включая Ubuntu) добавляет опцию в специфичном для Debian патче ( watch_exec_beep.patchэто «Mortys watch exec patch» из ошибки # 410967 ). Gentoo, возможно, принял аналогичный патч.
Жиль "ТАК - перестать быть злым"