Обработка кавычек и экранированных пробелов в аргументах команды Bash

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

whatIwant="command \"$filename-with-spaces-maybe\" -opt1 \"$some_words\" -opt2 $a_number  -opt3 \"$a_file_reference\" -opt4 \"$several_sentences\" "
eval $whatIwant

Хотя это работает, я опасаюсь использовать eval из-за риска того, что неправильное имя файла нанесет ущерб. Я хотел бы иметь возможность пропустить назначение переменной, а затем ее оценку, вместо того, чтобы просто поместить команду в начало строки и установить все аргументы соответствующими переменными, которые я создал ранее в сценарии.

Однако, когда я пытаюсь это сделать, имена файлов не рассматриваются как отдельные переменные, а вместо этого передаются команде в виде нескольких аргументов. Я пробовал несколько форм двойного экранирования, но мне не удалось найти что-то, что правильно оценивается. Это расстраивает, потому что, когда я возвращаю свою переменную, в которую я встраиваю команду, она идеально копирует и вставляет в командную строку и делает то, что я хочу.

Как лучше всего это сделать в сценарии bash?


person user2480136    schedule 08.07.2017    source источник
comment
Нам действительно нужно увидеть, чего вы хотите достичь, а не какую технику вы используете, чтобы дать действительно точный ответ. Тем не менее, ваш вопрос почти наверняка рассмотрен в BashFAQ #50.   -  person Charles Duffy    schedule 08.07.2017
comment
Кстати, shellcheck.net — ваш друг для выявления случаев, когда цитирование отсутствует/потеряно.   -  person Charles Duffy    schedule 08.07.2017
comment
Кроме того, command — это имя фактической встроенной команды, что делает его плохим именем для использования в качестве заполнителя/примера.   -  person Charles Duffy    schedule 08.07.2017


Ответы (1)


Это действительно так просто:

your_command "$filename_with_spaces_maybe" -opt1 "$some_words" -opt2 "$a_number" -opt3 "$a_file_reference" -opt4 "$several_sentences"

То есть:

  • Поместите каждое расширение параметра (где имя переменной заменяется ее значением) в двойных кавычках, даже если вы думаете, что значение будет только числовым.
  • Не беспокойтесь ни о каких eval, заданиях и т. д.

Единственные требуемые кавычки являются синтаксическими, а не буквальными — «вложенные» или «экранированные» кавычки — это буквальные символы без синтаксического значения, поэтому они не влияют на синтаксический анализ (без дополнительного шага синтаксического анализа, созданного eval, что действительно является плохой практикой). когда вообще можно избежать), и просто добавьте дополнительный нежелательный контент к фактически выполняемой команде.


Для случаев, когда вы считаете, что вам нужно сохранить команду в переменной по другим причинам (чтобы добавить аргументы только условно или иметь возможность ее повторного использования), см. BashFAQ #50.

Если вы еще не были убеждены, что eval — Плохая идея, вам следует прочитать BashFAQ #48< /а>.

Страница Wooledge на Цитаты — отличный ресурс для ответа на этот вопрос в целом.

person Charles Duffy    schedule 08.07.2017