Bash / sed字符串替换为文件内容(包含换行符)

时间:2013-12-20 23:01:45

标签: bash sed

Bash忍者的问题:我有一个XML模板文件,其中包含{{VARIABLE_NAME}}形式的一些模板标记,并希望用文本文件的内容查找/替换该标记的所有出现。

所以想象template.xml看起来像这样:

<?xml>
<root>
    <description>
        {{DESCRIPTION}}
    </description>
</root>

我有一个名为description.txt的文本文件可能包含任何字符(为简单起见,我们假设它已经是xml安全的)。我想用标记的内容替换标记,支持换行符和其他字符。

以前我一直在我的代码中这样做(这对于简单的字符串非常有用):

sed -i '' -e "s/{{DESCRIPTION}}/$DESCRIPTION/g" template.xml

但是,如果$DESCRIPTION包含换行符,则为sed balks:

sed: 1: "s/{{DESCRIPTION}}/Hello w ...": unescaped newline inside substitute pattern

是否有更好的方法可以执行此操作,或者我应首先使用$DESCRIPTION变量中的转义变体搜索/替换所有换行符。还有其他任何我需要逃脱的角色,比如/

3 个答案:

答案 0 :(得分:2)

这是一个用于替换的BASH(实际上是)脚本:

#!/bin/sh
while IFS= read -r line
do
    case "$line" in
        *{{DESCRIPTION}})
            cat "description.txt"
            ;;
        *)
            echo "$line"
            ;;
    esac
done <"template.xml"

在问题陈述中,“{{DESCRIPTION}}”单独出现在一行上。如果情况并非如此,则需要进行一些小的更改以保留该行上的其他数据。

答案 1 :(得分:1)

使用awk:

awk -v RS='\0' 'NR==FNR{r=$0;next}{sub(/\{\{DESCRIPTION\}\}/,r)}7' desc temp.xml

我想您知道如何使用重定向将输出保存到文件中。

test:在示例中,文件f包含许多“特殊”字符

kent$  cat f.xml
<?xml>
<root>
    <description>
        {{DESCRIPTION}}
    </description>
</root>

kent$  cat f
foo
'
"
O"'
/
\



        - 
bar

kent$  awk -v RS='\0' 'NR==FNR{r=$0;next}{sub(/\{\{DESCRIPTION\}\}/,r)}7' f f.xml
<?xml>
<root>
    <description>
        foo
'
"
O"'
/
\



        - 
bar

    </description>
</root>

答案 2 :(得分:1)

感谢您的回答。总是有兴趣学习在Bash中做事的新方法。我最后以不同的方式解决了它,但是,通过使用Bash的内置替换符号来转义字符串,我刚刚发现(sed因为我仍然不太清楚而导致失败):< / p>

DESCRIPTION=`cat description.txt`
DESCRIPTION=${DESCRIPTION//$'\n'/\\$'\n'} # escape newlines
DESCRIPTION=${DESCRIPTION//\//\\\/} # escape slashes
DESCRIPTION=${INPUT//$'&'/\\$'&'amp;} # escape ampersands
# other xml-escaping...

...然后使用sed在output.xml中实际替换内联:

cp -f template.xml output.xml
sed -i '' -e "s/{{DESCRIPTION}}/$DESCRIPTION/g" output.xml

由于换行符和斜杠现在已被转义(我错过了什么吗?)sed命令接受替换字符串而没有抱怨,它会完美呈现输出文件。