所以我加载一个属性文件来定义一些变量。在此示例中,假设它是一个mark!slash\ending\
名为 的字符串INPUT
。
INPUT
通过使用以下方式在属性文件中加载来声明:
. ./properties
在哪里
INPUT=mark!slash\ending\
我需要最终输出是通过 SED 形式运行的脚本s!@output@!$INPUT!g
,以便在执行时@output@
在另一个文件中替换为用户定义的属性文件中的输入(在本例中,变量为INPUT
)。我们在 SED 中使用分隔符,因此在添加到 SED 模板文件之前!
需要对该字符(以及任何 )进行转义。\
如果我尝试
echo SAFE_INPUT=$(printf '%s\n' 'mark!slash\ending\' | sed 's:[\!]:\\&:g')
我得到了预期的输出
mark\!slash\\ending\\
但是,如果我尝试
SAFE_INPUT=$(printf '%s\n' "${INPUT}" | sed 's:[\!]:\\&:g')
我明白了
mark\!slashending
我假设这与我的字符串与变量的声明有关,但我现在不知道其中的区别以及如何解决问题。
编辑:在进一步测试INPUT
时使用
. ./properties
打印为
mark!slashending
所以这不是 SED 的问题,而是读取属性文件的问题。
答案1
问题是当您INPUT
在文件中设置变量时properties
,如问题所示
INPUT=mark!slash\ending\
并将其作为 shell 脚本获取。
第一个\e
被 shell 替换为e
,\
如果后面有一些空格,则该行末尾的 将会被删除,否则表示该行在下一行中继续。所以 的值INPUT
已经被修改了。
您要么必须用引号定义您的输入
INPUT='mark!slash\ending\'
就像 Cornholio 的答案一样,否则你必须properties
以不同的方式解析你的文件。
使用以下命令,您会将变量 INPUT (以及其他变量,如果 中有更多行的话properties
)设置为正确的值。
eval $(sed -e 's:[\!]:\\&:g' properties)
这将使 shell eval
uate 命令的输出,sed
该命令替换的内容中的\
and和。结果将是具有原始名称等的变量。如果您的文件包含一个或多个变量分配,则这将起作用。对于其他 shell 脚本代码,它可能会给出奇怪的结果。!
properties
INPUT
properties
笔记:如果您的输入文件包含其他特殊字符,则处理会更加困难。因此,在没有额外检查的情况下使用eval
这种方式可能是脆弱或危险的。
根据您的示例,变量INPUT
将具有预期值mark!slash\ending\
之后你可以做
SAFE_INPUT=$(printf '%s\n' "${INPUT}" | sed 's:[\!]:\\&:g')
如果您需要变量SAVE_INPUT
来包含mark\!slash\\ending\\
.
更好的方法是逐行读取输入,while read -r line
并检查和处理该行以分隔变量名称和值。
答案2
如果我使用引用的值执行以下操作INPUT
,它会起作用:
> INPUT='mark!slash\ending\'
> SAFE_INPUT=$(printf '%s\n' "${INPUT}" | sed 's:[\!]:\\&:g')
> echo $SAFE_INPUT
mark\!slash\\ending\\
请注意,这是您的脚本的精确副本,INPUT=
由我添加。