给定这个关联数组:
declare -A variables=(
[prefix]='/usr'
[exec_prefix]='@prefix@'
[libdir]='@exec_prefix@/lib'
)
我想替换任何出现的模式@([^@/]+)@
(例如@prefix@
,其中prefix
是捕获),其值与捕获相关联(例如所有值都/usr
prefix
},以便递归执行替换,直到不再出现。数组中每个键的步骤如下:
无论采用何种方法,所期望的结果都是:
prefix=/usr
exec_prefix=/usr
libdir=/usr/lib
其他要求:
prefix=@prefix@
)。Lua中的例子:
local variables={
prefix="/usr",
exec_prefix="@prefix@",
includedir="@prefix@/include",
libdir="@exec_prefix@/lib",
random_one_to_show_off_fancy_recursion="@prefix@@libdir@@includedir@"
}
function replacer( variable )
return compute_value(variables[variable])
end
function compute_value( s )
return s:gsub('@([^@/]+)@',replacer)
end
local variable, value = next(variables)
while variable do
variables[variable] = compute_value(value)
print( string.format('%-39s\t%s', variable, variables[variable]) )
variable, value = next(variables,variable)
end
答案 0 :(得分:2)
下面的(纯Bash)代码假设'@@'保持不变,当'xyz'不是变量时,'@ xyz @'保持不变。它还尝试检测递归变量定义,包括间接变量定义(例如[a]=@b@ [b]=@c@ [c]=@a@
)。
# Regular expression for a string with an embedded expansion
# For a string of the form 'u@v@w', where 'u' and 'v' do not contain '@':
# u -> BASH_REMATCH[1]
# v -> BASH_REMATCH[2]
# w -> BASH_REMATCH[3]
readonly EXPANSION_RX='^([^@]*)@([^@]*)@(.*)$'
# First pass tries to expand all variables
vars_to_expand=( "${!variables[@]}" )
while (( ${#vars_to_expand[*]} > 0 )) ; do
old_vars_to_expand=( "${vars_to_expand[@]}" )
vars_to_expand=()
for var in "${old_vars_to_expand[@]}" ; do
val=${variables[$var]}
unexpanded=$val
newval=
while [[ $unexpanded =~ $EXPANSION_RX ]] ; do
newval+=${BASH_REMATCH[1]}
v=${BASH_REMATCH[2]}
unexpanded=${BASH_REMATCH[3]}
if [[ $v == "$var" ]] ; then
echo "ERROR - Expanding '@$var@' in '$var'" >&2
exit 1
elif [[ -z $v ]] ; then
# The empty string can not be a hash key (Duh!)
newval+=@$v@
else
newval+=${variables[$v]-@$v@}
fi
done
newval+=$unexpanded
if [[ $newval != "$val" ]] ; then
# An expansion has occurred.
# Update the variable value
variables[$var]=$newval
# Further expansions may be possible, so add the variable to the
# list of variables to be expanded again
vars_to_expand+=( "$var" )
fi
done
done