我正在尝试编写一个脚本,该脚本查找特定模式({?varname}
)中的字符串并将其替换为相应的环境变量。
这是我到目前为止所拥有的:
function get_env() {
var=$1
echo ${!var}
}
sed -e 's/{?\([a-z]*}\)/'$(get_env '\1')'/g' file.txt
该功能有效,例如get_env LOGNAME
-->dotan
sed 返回函数的值,例如,如果我将函数的内容替换为,echo __$1__
我将得到{?logname}
-->__LOGNAME__
然而,组合起来却不起作用。就好像函数总是返回一个空字符串。
我不确定是什么导致了这里的问题。有任何想法吗?
答案1
该命令行将get_env '\1'
在命令替换中运行,并将其输出粘贴到sed
.您可能应该收到一个错误,因为\1
不是变量的有效名称。
你可以使用 Perls/\{\?([a-z]+)\}/$ENV{$1}/
来做到这一点;%ENV
是包含环境变量的哈希:
$ export name=you
$ echo "hello {?name}" | perl -pe 's/\{\?([a-z]+)\}/$ENV{$1}/'
hello you
(GNU sed 有e
运行外部程序的命令,但它使用运行整个模式空间,而不仅仅是匹配部分,因此它似乎不太适合这里。)
纯粹在 Bash 中,如果你坚持 ( setvar.sh
):
#!/bin/bash
while IFS= read -r line ; do
while [[ $line =~ ^(.*)(\{\?[a-zA-Z0-9_]+\})(.*)$ ]] ; do
varname=${BASH_REMATCH[2]}
varname=${varname#"{?"}
varname=${varname%\}}
printf -v line "%s%s%s" "${BASH_REMATCH[1]}" "${!varname}" "${BASH_REMATCH[3]}"
done
printf "%s\n" "$line"
done < "${1-/dev/stdin}"
$ echo 'foo {?BASH_VERSION} {?blah} bar' |blah=ABC bash setvar.sh
foo 4.4.12(1)-release ABC bar
答案2
这是我想出的解决方案
grep -o '{?\S*}' file.txt | sed 's/{?\(.*\)}/\1/' | xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"
分解它:
grep -o '{?\S*}' file.txt
- 获取所有要替换的变量sed 's/{?\(.*\)}/\1/'
- 删除格式xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"
- 分别搜索和替换每个变量