我正在尝试在特定搜索字符串之后将包含一堆文件名(包括目录斜杠)的字符串添加到文件中。
我已经创建了这样的输入文本:
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
我知道这必须是一个简单的字符串操作问题或关于引号的东西,但我在这里尝试了很多组合,但无法弄明白...
答案 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
。