在文件中查找字符串并使用bash和sed添加内容

时间:2014-04-15 20:19:05

标签: string bash sed

我正在尝试在特定搜索字符串之后将包含一堆文件名(包括目录斜杠)的字符串添加到文件中。

我已经创建了这样的输入文本:

for f in /tmp/et/*.rules; do 
    #STRING+=`basename "$f"`$'\n'; 
    STRING+=$'include $RULE_PATH/et/'`basename "$f"`$'\n'
done

使$STRING相等:

include $RULE_PATH/et/emerging-activex.rules
include $RULE_PATH/et/emerging-attack_response.rules
include $RULE_PATH/et/emerging-botcc.portgrouped.rules
include $RULE_PATH/et/emerging-botcc.rules
include $RULE_PATH/et/emerging-chat.rules
include $RULE_PATH/et/emerging-ciarmy.rules
include $RULE_PATH/et/emerging-compromised.rules
include $RULE_PATH/et/emerging-current_events.rules
include $RULE_PATH/et/emerging-deleted.rules
include $RULE_PATH/et/emerging-dns.rules

和我添加sed内容的$STRING命令如下所示:

sed -i.bak 's!^#EMERGING\ THREATS\ RULESET.*$!& \n'"$STRING"'!' snort.conf

这是在匹配文字后的新行上查找文字#EMERGING THREATS RULESET并添加$STRING

我必须将默认的sed分隔符更改为其他内容,因为默认/与我$STRING中的目录路径冲突。现在,问题是我从sed收到错误说明:

sed: -e expression #1, char 82: unterminated `s' command

我知道这必须是一个简单的字符串操作问题或关于引号的东西,但我在这里尝试了很多组合,但无法弄明白...

2 个答案:

答案 0 :(得分:3)

好的,请使用这种方法:

#!/bin/bash
> _tmp
for f in /tmp/et/*.rules; do 
    echo $'include $RULE_PATH/et/'`basename "$f"`$'\n' >> _tmp
done

sed -i.bak '/^#EMERGING THREATS RULESET/r _tmp' snort.conf

这基本上将您的输出存储在临时文件中,并使用该临时文件在搜索模式后替换sed命令中的内容。

答案 1 :(得分:2)

<击> 您使用的分隔符不正确:

sed -i.bak 's!^#EMERGING\ THREATS\ RULESET.*$/& \n'"$STRING"'!' snort.conf
                                             ^
                                             |
---------------------------------------------

<击>

所以看来你的问题是未转义的换行符。您不能在sed替换文字(示例中为$STRING)中使用未转义的换行符。 sed脚本使用新行就像shell一样,来终止命令。

如果替换文本中需要换行符,则需要在其前面加上反斜杠。或者,如果您正在使用gnu sed并且不关心其他sed实现的可移植性,则可以在替换文本中替换带有\n的换行符(所有符合posix标准的seds都允许正则表达式,但不是替换,因为它是gnu扩展名)。由于您的嵌入式换行符在变量中,因此这种方法不适用于您。

因此,您可以按照@anubhava在答案中显示,或者使用awk解决方案:

awk -v patt="$STRING" '/^#EMERGING THREATS RULESET/{print $0;print patt;next}1' snort.conf >tmp && mv tmp snort.conf

这不需要GNU awk