我有一个文本(配置)文件,但不幸的是读取该文件的程序不允许使用任何类型的变量。因此,我想使用一个预处理器来替换配置文件中的一组占位符,然后再将其传递给程序。
我可以以任何我想要的方式定义变量的格式(例如§SOME_DIR
)。如果我只有几个变量,我可能会使用sed
:
sed -e "s*§SOME_DIR*$SOME_DIR*g" my.conf | target_prog
但变量列表相当长,而且应该很容易配置 - 所以我更喜欢将变量放在属性文件中,例如
SOME_DIR=...
OTHER_DIR=...
...
然后打电话
some_replace_tool my.properties my.conf | target_prog
我正在寻找“some_replace_tool”。有任何想法吗?
答案1
我可能会编写一些脚本来扩展 shell 变量以生成输出配置文件。
以下是一些提示:
- 这里的字符串 (<<<) 被扩展
- 您可以通过“.variables.conf”加载变量
env -i script.sh
将在干净的环境中运行脚本(没有额外的变量)
因此,脚本必须构建一个新的临时脚本,该脚本将获取变量并使用扩展的变量来 cat 这里字符串。然后要获得最终输出,您必须通过 运行临时生成的脚本env -i
。
答案2
@fred 有一些正确的想法,但一个更简单的系统可能是:
sed -ne '/^#/d;s!^\([^=]*\)=\(.*\)$!s@\1@\2g!p' my.proprties > script.sed
sed -f script.sed my.conf | target_prog
这也仅生成具有“PROP=VALUE”的行并忽略注释行。
打破这个:
/^#/d - delete any comment lines (to ignore #PROP=VALUE)
s!^\([^=]*\)=\(.*\)$ - match any line with PROP=VALUE and place PROG into group 1 and VALUE into group 2
!s@\1@\2@g - replace with s@GROUP1@GROUP2@g
!p - print the line, to override the -n
您最终会得到一个如下所示的 sed 脚本:
s@PROP1@VALUE1@g
s@PROP2@VALUE2@g
...
答案3
有两个预处理器可以声称是传统的 UNIX 预处理器:程序文件(C 预处理器)和米4。两者都不太适合一般预处理,因为它们会替换文本中任何位置的单词,并且在 cpp 的情况下会强加注释语法。一个合理的通用预处理器将有一个宏指示符(即不扩展每次出现的name
,仅扩展@name
(例如))。
我认为没有任何预处理器是事实上的标准,甚至只是通用的。一种适用于多种输入格式并可在许多 Linux 发行版上使用的工具是总计划。
如果您想坚持使用标准工具,在某些情况下可以使用 shell 作为预处理器。构建一个字符串,然后运行
eval 'preprocessed=$(cat <<EOF)
$template
EOF'
Shell 参数和命令 ( $var
, $(command)
, `command`
) 将被扩展。请注意,您无法轻易阻止模板调用外部命令或分配给脚本使用的变量,因此除非您信任模板的来源,否则不要使用此功能。
答案4
更新:扩展Arcege
sed-to-sed 的想法,您可以为 find/repl 模板提供更易于管理的布局(表格或参差不齐),它可以是内联的......并且不需要中间文件:(g
在 之前添加p'<<'EOF'
可以对每行进行多个更改...请注意foo
,barbar
、 等将被视为sed
正则表达式。
I=$'\01'; sed -nre "s/^([^ ]+) +/s$I\1$I/;s/$/$I/p"<<'EOF' |sed -f - file
foo By the middle of June,
barbar mosquitos were rampant,
foofoofoo the grass was tawny, a brown dust
barbarbarbar haze hung over the valley
EOF
(原帖)
您可以将sed
其用作可执行脚本,带有包装器...
您可以在单独的文本文件中定义查找和替换文本,
但对于此示例,它是内联定义的...
该脚本将 find/repl 对转换为 sed 表达式并动态创建可执行脚本
I=$'\01'; set -f
printf "#!/bin/sed -f\n" > ~/bin/script.sed
while IFS= read -r line ;do
ix=$(expr index "$line" " ")
printf "s%s%s%s%s%s\n" $I ""${line:0:$((ix-1))}"" $I "${line:$ix}" $I
done <<'EOF' >> ~/bin/script.sed
$text1 By the middle of June,
$text2 mosquitos were rampant,
$text3 the grass was tawny, a brown dust
$text4 haze hung over the valley
EOF
chmod +x ~/bin/script.sed
这是要修改的测试文件。
'$' 没问题,因为它不在行尾(对于 sed),并且它在任何时候都不会暴露给 shell,但任何不会与之冲突的标记sed
都可以。你甚至可以使用#
echo '$text1 $text2 $text3 $text4' > file
假设这~/bin
是一个 $PATH 目录,则运行的命令是:
script.sed file