косвенное выполнение команды 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там? Если так, я был бы рад услышать причины.

Другие вопросы по тегам