Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux sed两个模式搜索,并在第二个模式最后一次出现后追加行_Linux_Unix_Sed_Awk_Grep - Fatal编程技术网

Linux sed两个模式搜索,并在第二个模式最后一次出现后追加行

Linux sed两个模式搜索,并在第二个模式最后一次出现后追加行,linux,unix,sed,awk,grep,Linux,Unix,Sed,Awk,Grep,在过去的两天里,下面的sed问题一直让我头疼不已 我有以下文件(iptables): 我想使用sed搜索模式*过滤器,如果匹配,则搜索第二个模式[0:0],然后在第二个模式最后一次出现后添加一行 这将(理想情况下)导致: 这里的论坛给了我一个良好的开端,但我就是无法解决这个具体问题 到目前为止,我有以下解决方案,但它在第二个模式第一次出现后添加了一行[0:0]: sed -n '/\*filter/{:a;N;/^\n/s/^\n//;/\[0:0\]/{!ba;p;s/.*/TESTLINEA

在过去的两天里,下面的
sed
问题一直让我头疼不已

我有以下文件(iptables):

我想使用
sed
搜索模式
*过滤器
,如果匹配,则搜索第二个模式
[0:0]
,然后在第二个模式最后一次出现后添加一行

这将(理想情况下)导致:

这里的论坛给了我一个良好的开端,但我就是无法解决这个具体问题

到目前为止,我有以下解决方案,但它在第二个模式第一次出现后添加了一行
[0:0]

sed -n '/\*filter/{:a;N;/^\n/s/^\n//;/\[0:0\]/{!ba;p;s/.*/TESTLINEADDEDBYSED/;};ba}; p' file
我假设在第二个分支中使用
*
,我会使用(读:skip?)第一次出现的
[0:0]

我在这里误解了什么?

方法稍有不同,因为
sed
对新行非常糟糕

基本上,我把所有的东西都放在一行,用一个
@
替换换行符,用贪婪匹配进行替换,最后把换行符放回去

$ cat input | tr '\n' '@' | sed s'/\(\*filter.*\[0:0\]\)/@@\1@TESTLINEADDEDBYSED/' | tr '@' '\n'
someline

someline


*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

TESTLINEADDEDBYSED

someline
如果文件中的行数太多,这是一种糟糕的方法

这个怎么样:

fgrep-q'*filter'文件和&tac文件| awk'!f&/\[0:0\]/{$0=“FOO\n\n”$0;f=1}1'| tac
某物
某物
*滤器
:输入接受[0:0]
:正向接受[0:0]
:输出接受[0:0]
福
某物
首先
fgrep
用于
文件中的固定字符串
*过滤器
,如果找到,则在包含
[0:0]
的最后一行后插入行
FOO
tac
用于反向读取文件,因此不需要读取文件两次或缓冲区来查找最后一次,因为查找第一次比较容易


如果文件的大小不是很大,则使用
awk
进行两次传递:

awk 'FNR==NR{if($0~/*filter/)a=1;if(a&&$0~/\[0:0\]/)b=NR;next}FNR==b{$0=$0"\n\nFOO"}1' file file

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

FOO

someline

虽然我的第一个想法是只使用sed,但我必须承认,我也喜欢这种简单而优雅的方法。谢谢有时链接现有的实用程序可能是一种更简单的方法,我在我的答案中添加了一个只使用
awk
的两遍方法来进行对比。因此答案在于制作一个大行(使用分隔符),然后编辑该行,然后再将其拆分为多行?非常有趣!谢谢@sudo_O-好痛!我通常是处理UOOC奖项的人:-)@cybernijntje-很高兴你喜欢它。别忘了投票:-)@Fredrik haha
;)别忘了OPs代表还没到投票的高度@是的+即使我受伤了,我对你也很强硬
$ cat input | tr '\n' '@' | sed s'/\(\*filter.*\[0:0\]\)/@@\1@TESTLINEADDEDBYSED/' | tr '@' '\n'
someline

someline


*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

TESTLINEADDEDBYSED

someline
awk 'FNR==NR{if($0~/*filter/)a=1;if(a&&$0~/\[0:0\]/)b=NR;next}FNR==b{$0=$0"\n\nFOO"}1' file file

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

FOO

someline