Я думаю, что ваше собственное решение с использованием $ {OPT1 + -o "$ OPT1"} является хорошим решением, и я не вижу никаких проблем с этим в этом сценарии использования, но есть другой подход, использующий evalчто никто не упомянул, что еще ближе к вашему исходному коду:
#!/bin/sh
FILE1='some file'
FILE2='another file'
if [ somecriteria = true ]; then
OPT1="-o '$FILE1'"
fi
if [ othercriteria = true ]; then
OPT2="-p '$FILE2'"
fi
eval myutil "$OPT1" "$OPT2"
Это будет производить то, что вы хотите.
Но вы должны быть осторожны, если ваши имена файлов содержат одинарные кавычкикак часть буквальной строки имени файла.
Если вы точно знаете, как выглядят ваши имена файлов при написании сценария, просто убедитесь, что литералы кавычек вашего имени файла не выходят за пределы того, что вы используете для обозначения имени файла.
Но это еще важнее, когда вы обрабатываете пользовательский ввод или иным образом получаете информацию из окружения.- например, если $ FILE1 определен как abc'; /tmp/malicious_program '
, а затем вы выполняете eval, он разберет строку myutil в:
myutil -o 'abc'; /tmp/malicious_program '' -p 'another file'
.., которая является двумя отдельными командами и может быть массивнойдыра в безопасности, в зависимости от того, как именно выполняется этот скрипт относительно сущности, которая создала / tmp / malware_program и установила $ FILE1.
В тех случаях, если вы хотите ввести зависимость от sed, вы можетесначала сделайте что-то вроде этого:
FILE1=\'`printf %s "$FILE1" | sed "s/'/'\\\\''/g"`\'
.. это создаст красивое экранированное имя, заключенное в одинарные кавычки, и любые экранированные кавычки внутри него также будут экранированы.
Поскольку в Борне /Оболочка POSIX, кроме одной кавычки, не может «вырваться» из строки в одинарных кавычках, поэтому в своем примере я использую одинарные кавычки.Двойная кавычка, избегая вещей таким образом, возможна, но ваша команда sed должна быть намного более сложной, так как есть несколько других символов, которые вам нужно экранировать внутри двойных кавычек (в верхней части моей головы: вместо того, чтобы просто избегать одиночных кавычек, вы избегаете двойных кавычек, обратная косая черта, обратные косые черты, знаки доллара и, возможно, другие вещи, о которых я не думаю).
PS: потому что я нашел такой подход «завершение в оболочку, затем подтверждение позже» полезным в нескольких случаях, впо крайней мере, там, где это было совершенно необходимо, я написал крошечную C-программу (и эквивалентную функцию оболочки, использующую sed), которая оборачивает все свои аргументы в экранирование одинарной кавычки, как описано выше, на случай, если кто-то захочет использовать ее вместо того, чтобы реализовывать вашусобственный: esceval