косвенное выполнение команды bash не работает должным образом с coproc
Я новичок в написании сценариев оболочки Linux, и у меня есть вопрос:
1.) почему команда
test1="leafpad" && coproc exec "$test1"
работают в bash (командная строка, GNU bash 4.4.12 на производном Linux Debian), но команда
test1="coproc" && exec "$test1" leafpad
не? Сообщения об ошибках:bash: exec: coproc: Not found.
в то время как
coproc leafpad
работает, как ожидалось.
Как правильно указать эту команду, чтобы она работала? Я уже пробовал
test1=`coproc` && exec "$test1" leafpad
test1='coproc' && exec "$test1" leafpad
test1="'coproc'" && exec "$test1" leafpad
test1=`coproc` && exec '$test1' leafpad
test1=`coproc` && exec `$test1` leafpad
test1="coproc" && exec $test1 leafpad
test1=`coproc` && exec $test1 leafpad
и еще несколько вариантов, но ни одна из них не работает.
2.) Это был тест только в командной строке. Но мне, скорее, нужно сделать это внутри сценария: так что я уверен, что нужно сделать некоторые дополнительные цитаты или маскировку специальных символов.
Предыстория: мне нужно выполнить команду, содержащую множество аргументов, некоторые из которых заменены переменными. Подумайте о чем-то вроде yad со всеми его возможными аргументами в нескольких строках, но давайте создадим более простой пример:
my_codeset="437"
my_line="20"
my_filename="somthing.txt"
if [ $value == 0 ]; then my_tabwidth='--tab-width=10'; else my_tabwidth=""; fi # set tabs or not
leafpad --codeset="$my_codeset" "$my_tabwidth" --jump="$my_line" "$my_filename"
при этом указанные переменные могут быть изменены в зависимости от предыдущего взаимодействия с пользователем.
Теперь эта полная команда (которая в оригинале составляет около 6 строк кода) должна быть выполнена в двух вариантах: один раз во главе с coproc, а другой раз нет, как функция условного перехода.
так что я хочу:
if [ $something == 1 ]; then copr_this="coproc"; else copr_this=""; fi
exec '$copr_this' <mycommand, with all its quoted arguments>
вместо
if [ something == 0]; then
lengthy command here
else
coproc lengthy command here, exactly repeated.
fi
Я уже пытался сделать это наоборот: поместить всю длинную команду в переменную и выполнить ее в условной ветке:
my_command=`lengthy command with some arguments $arg1 $arg2 ...`
if...
exec "$my_command"
else
coproc exec "$my_command"
fi
который также остановился с сообщением об ошибке «не найдено». Различные способы цитирования не решали ее, а только приводили к разным сообщениям об ошибках. Подобрать правильную расценку для этой задачи мне не удалось. Насколько правильно читается этот qouting?
Конечно, я мог бы повторить 6 командных строк в коде, но я уверен, что это можно было бы сделать более удобным.
Как было сказано в начале: Непрямое выполнение команды работает в командной строке (а также внутри скрипта), пока coproc не задействован . Я не могу заставить его работать с coproc.
Любая помощь и подсказки приветствуются.
Обновление после первого ответа от @Socowi:
Спасибо за исчерпывающий и быстрый ответ, Socowi. Очевидно, вы правы, что не подчиняетесь команде. Теперь я понимаю, почему мои попытки потерпели неудачу. В
exec
команда была добавлена только во время моих экспериментов. Я начал без этого, но, не добившись успеха, подумал, что это может помочь. Это был просто акт отчаяния. Обратные кавычки в строке
my_command=`lengthy command with some arguments $arg1 $arg2 ...`
были опечаткой, как вы отметили, должны были быть нормальные кавычки, поскольку я намеревался выполнить команду в
if
конечно. Я, наверное, пойду по тому пути, по которому вы меня указали, используя
function {...}
внутри скрипта. Но, поэкспериментировав тем временем над этим вопросом, я пришел к удивительному решению: удивительно для меня из-за разницы между
coproc
не быть командой и
leafpad
с его двоичным кодом, являющимся командой. Итак, должно быть ясно, что
test1='coproc' && test2='leafpad' && "$test1 $test2"
выдаст сообщение об ошибке
bash: coproc leafpad: command not found.
, что является правдой. Но теперь: зачем
test1='coproc' && test2='leafpad' && /bin/bash -c "$test1 $test2"
выполнить работу, запустив листовую панель, позволяя вводить дальнейшие команды в bash параллельно, как если бы я ввел
leafpad &
Только? Но на этот раз выполнение как встроенной (или ключевого?), Так и команды из переменной , в которой было отказано при попытке ввести ее непосредственно в первом экземпляре bash. Что верно для первого экземпляра bash, должно быть верно и для второго, или у меня ложная точка зрения? Почему так работает? Есть ли
-c
вариант сделать что-нибудь еще, кроме как выполнить команду?
1 ответ
Цитирование здесь не проблема. Есть еще две проблемы:
Порядок and и встроенных и двоичных файлов
test1="leafpad" && coproc exec "$test1"
такой же как
coproc exec leafpad
.
test1="coproc" && exec "$test1" leafpad
такой же как
exec coproc leafpad
.
Порядок имеет значение: vs.
exec coproc
. Последний не работает, так как заменяет текущую оболочку указанной программой. Однако это встроенная команда. В вашей системе нет двоичного файла. Запускать можно только изнутри
bash
. Поэтому не получается.
Подстановка команд против строк
В вашем сценарии ...
my_command=`lengthy command`
if ...; then
exec "$my_command"
else
coproc exec "$my_command"
fi
... вы не хранили
lengthy command
внутри переменной, но вы выполнили эту команду и сохранили ее вывод (
v=`cmd`
такой же как
v=$(cmd)
) перед
if
. Затем внутри if вы попытались выполнить вывод команды как другую команду.
Чтобы сохранить команду в виде строки и выполнить ее позже, вы можете использовать
my_command="lengthy command"; $my_command
(обратите внимание на намеренно пропущенные кавычки). Однако bash предлагает гораздо лучшие способы хранения команд. Вместо строк используйте массивы или функции. Здесь мы используем функцию:
my_command() {
exec lengthy command
}
if ...; then
coproc my_command
else
my_command
fi
coproc exec
?
При этом меня действительно интересует сочетание и. Мне кажется
coproc exec cmd
игнорирует часть и совпадает с
coproc cmd
. Если бы здесь действовали нормально, текущая оболочка была бы заменена, вы бы потеряли
COPROC
массив и, следовательно, не потребуется
coproc
. В любом случае использование обоих одновременно кажется странным. Вы действительно уверены, что вам это нужно?
exec
там? Если так, я был бы рад услышать причины.