这是模板变量 VAR1,需要根据 VAR2 进行更新,变量的顺序如下,如何在没有 sed 命令的情况下更新 VAR1
#!/bin/bash
VAR1="<tr>
<th>\$VAR2</th>
</tr>"
VAR2=test
echo $VAR2
答案1
你可以使用envsubst
:
(使用任何 POSIX shell,包括bash
):
VAR1="<tr>
<th>\$VAR2</th>
</tr>"
VAR2=test
expanded_VAR1=$(
export VAR2
printf '%s\n' "$VAR1" |
envsubst '$VAR2'
)
或者执行所有字扩展(参数扩展、命令替换、算术扩展)之上参数扩展,您可以使用zsh
及其e
参数扩展标志:
#!/bin/zsh -
VAR1="<tr>
<th>\$VAR2</th>
</tr>"
VAR2=test
expanded_VAR1=${(e)VAR1}
在 POSIX shell 中,您可以使用 aeval
和 here-document 执行类似的操作:
VAR1="<tr>
<th>\$VAR2</th>
</tr>"
VAR2=test
expanded_VAR1=$(eval "cat << EOF
$VAR1
EOF")
bash
或 的另一个选项zsh
是使用printf
:
VAR1='<tr>
<th>%s</th>
</tr>'
VAR2=test
printf -v expanded_VAR1 -- "$VAR1" "$VAR2"
使用zsh
(但不使用bash
),您可以使用%n$s
语法(就像在许多printf(3)
实现中一样)来引用n
th参数:
#! /bin/zsh -
VAR1='<tr>
<th>%1$s</th> <th>%1$s again</th> <th>%2$s</th>
</tr>'
VAR2=test VAR3=test2
printf -v expanded_VAR1 -- "$VAR1" "$VAR2" "$VAR3"
或者使用任意命名格式指令(仅限于除, , NUL 和十进制数字zformat
之外的单字节字符):-
.
#! /bin/zsh -
VAR1='<tr>
<th>%a</th> <th>%a again</th> <th>%b</th>
</tr>'
VAR2=test VAR3=test2
zformat -f expanded_VAR1 "$VAR1" "a:$VAR2" "b:$VAR3"
使用ksh93
,您可以使用%H
代替%s
in itprintf
来正确编码 HTML 中的特殊字符(例如,&
变为&
),但对于非 ASCII 字符,它只能在使用 iso8859-1 字符集的区域设置中正常工作。ksh93
不printf
支持-v
,不过可以用expanded_VAR1=${ printf... ;}
。
使用printf
/方法,模板中的zformat
文字字符可以转义为(和中一样),使用/ +here-doc 方法,可以通过在/ /前面加上 前缀来转义它们。有了,AFAIK,就无法逃脱。%
%%
\
\\
printf
e
eval
$
`
\
\
envsubst
$
答案2
您可以使用参数扩展将 var1 中的唯一字符串替换为 var2 的值:
var1='<tr>
<th>unique_placeholder_var2</th>
</tr>'
var2=test
echo "${var1/unique_placeholder_var2/"$var2"}"
答案3
假设var1
包含格式良好的 XML:
var1='
<tr>
<th>$var2</th>
</tr>
'
var2=test
然后,您可以使用shell 变量的xmlstarlet
值替换所有th
具有文字值的节点的值,如下所示:$var2
var2
var1=$( printf '%s\n' "$var1" | xmlstarlet ed -u '//th[text() = "$var2"]' -v "$var2" )
这会xmlstarlet
调用 XPATH 查询,选择th
我们想要修改的所有节点。 xmlstarlet
将用 shell 变量的值替换这些节点的值var2
,并将结果写入标准输出。
$ printf '%s\n' "$var1"
<?xml version="1.0"?>
<tr>
<th>test</th>
</tr>
请注意,这将正确编码该值var2
以包含到您的 XML 文档中:
$ var1='
<tr>
<th>$var2</th>
</tr>
'
$ var2='HÉLLO :->'
$ var1=$( printf '%s\n' "$var1" | xmlstarlet ed -u '//th[text() = "$var2"]' -v "$var2" )
$ printf '%s\n' "$var1"
<?xml version="1.0"?>
<tr>
<th>HÉLLO :-></th>
</tr>
答案4
替换模板中变量的通用方法:
- 使用bash正则表达式捕获变量名(由于贪心匹配,这里从右到左匹配变量名
- 使用变量间接获取变量值
- 从输入字符串中删除匹配的 varname 以避免无限循环(这会破坏原始字符串,如果您进一步需要,请备份它)
示范
设置模板和(不是全部)要替换的变量
VAR1="<tr> <th>\$VAR2</th> <th>\$VAR3</th> </tr>" VAR2=test unset VAR3
执行替换
result="" while [[ $VAR1 =~ (.*)\$([[:alpha:]_][[:alnum:]_]*)(.*) ]]; do varname=${BASH_REMATCH[2]} [[ -v $varname ]] && replacement=${!varname} || replacement="\$${varname}" result="${replacement}${BASH_REMATCH[3]}${result}" VAR1=${BASH_REMATCH[1]} done result="${VAR1}${result}" declare -p result
检查结果
declare -- result="<tr> <th>test</th> <th>\$VAR3</th> </tr>"
这需要-v
操作员使用 bash 版本 4.3+。