#regex #bash
#регулярное выражение #bash
Вопрос:
У меня есть функция read_command, определенная как:
function read_command {
local __newline __lines __input __newstr __tmp i;
exec 3< "$*";
__newline=$'n';
__lines=();
while IFS= read <amp;3 -r __line amp;amp; [ "$__line" != '####' ]; do
echo "$__line";
__lines =("$__line");
done
while IFS= read <amp;3 -r __line amp;amp; [ "$__line" != '####' ]; do
read -e -p "${__line#*:}$PS2" __input;
local ${__line%%:*}="$__input";
done
__command="";
for i in "${__lines[@]}"; do
__tmp=$(echo "${i}");
__command="${__command} ${__newline} ${__tmp}";
done
echo -e "$__command";
}
В текущем каталоге есть файл с именем «test» со следующим
содержимым:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
####
a: name of friend a
b: name of friend b
####
В терминале выполняется команда
read_command test
Без ввода я ожидаю, что вывод последнего оператора будет:
greet Bob
greet Jim
Но то, что я получаю, это:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
Что здесь не так?
Редактировать: как предложил Дэвид, добавление eval работает в некоторых случаях, кроме следующего.
j=1;i="export DISPLAY=:0 amp;amp; Xephyr :${j}amp;";k=$(eval echo "$i");
echo $k
экспорт ОТОБРАЖЕНИЯ =:0
Я ожидаю, что k будет «export DISPLAY=:0 amp;amp; Xephyr :1 amp;», что здесь не так? Редактировать: я попробовал со следующим
k=$(eval "echo "$i"")
Это ссылка на скрипт, над которым я работаю.
https://gist.github.com/QiangF/565102ba3b6123942b9bf6b897c05f87
Комментарии:
1. Точки с запятой в конце строки являются излишними; в сценарии оболочки в качестве разделителя команд достаточно новой строки или точки с запятой.
2. Я просто следую примеру, в Интернете слишком много плохих примеров.
Ответ №1:
Во время первого while
цикла, в echo "$__line"
, у вас есть __line='greet ${a:-"Bob"}'
. Когда вы попытаетесь это напечатать, Bash не будет расширяться ${a:-"Bob"}
Bob
. (Даже если вы удалите кавычки $__line
, этого не произойдет.) Чтобы получить этот эффект, вам нужно добавить eval
, как, например, eval echo "$__line"
. К сожалению eval
, поставляется с банкой червей, вам нужно начать беспокоиться о взаимодействии между уровнями цитирования и тому подобным.
Комментарии:
1. Как предотвратить выполнение команды eval echo $ __line в __line, см. Редактирование в вопросе.
2. Это очень похоже на проблему XY . Какую проблему вы на самом деле пытаетесь решить с помощью этого кода? Это также смутно похоже на mywiki. wooledge.org/BashFAQ/050
3. Альтернатива обману. sh должен использовать замену шаблона, но это менее удобно. ( github.com/tests-always-included/mo )
4.
eval
использует первичный уровень цитирования, что означает, что:eval $v
иeval "$v"
сделайте то же самое для всего содержимого$v
. Чтобы управлять тем, чтоbash
происходит после расширенияeval
аргументов, вам нужно использовать кавычки второго уровня, то есть кавычки, которые не будут использоваться на первом уровне. Итак, попробуйтеeval echo "$line"
. Все быстро становится неприятным, если$line
также содержит кавычки, но, похоже, в вашем случае это не так, так что все должно быть в порядке.