使用sed,当在两个模式中找不到另一个模式时,如何在两个模式之间添加文本?

使用sed,当在两个模式中找不到另一个模式时,如何在两个模式之间添加文本?,sed,Sed,使用sed,当在两个模式(此处Pattern\u one和Pattern\u two)之间找不到另一个模式(此处Pattern\u interest)时,如何在其中添加文本(例如此处Inserted\u text) 在我的文件中,行尾字符只是一个\n(即Unix格式),但我在msdos下使用GNU版本4.0.7 我尝试过但无效的命令: sed -i ":a;N;$!ba;/\nPattern_one/ /\nPattern_of_interest/! /\nPattern_two/ a/Inse

使用sed,当在两个模式(此处
Pattern\u one
Pattern\u two
)之间找不到另一个模式(此处
Pattern\u interest
)时,如何在其中添加文本(例如此处
Inserted\u text

在我的文件中,
行尾
字符只是一个
\n
(即Unix格式),但我在msdos下使用GNU版本4.0.7

我尝试过但无效的命令:

sed -i ":a;N;$!ba;/\nPattern_one/ /\nPattern_of_interest/! /\nPattern_two/ a/Inserted_text/" file.txt
这些模式都是从一行的开头开始的

下面例子中的“blabla”可以是任何东西

输入文件的示例:-

blabla
blabla
Pattern_one
Pattern_of_interest blabla
blabla
Pattern_two
blabla
blabla
blabla
blabla
Pattern_one
Pattern_two
blabla
blabla
blabla
Pattern_one
blabla
blabla
Pattern_two
blabla
blabla
所需的输出文件(插入在顶部、下方、图案旁边):

所需的输出文件(底部插入,iow,图案二旁边):

我需要在顶部插入,但如果您也能告诉我如何在底部插入,那也很好。

它就在那里: 而且
oldfile.txt
file.txt
之间有区别:

diff -W 60  -y oldfile.txt file.txt
blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
Pattern_of_interest blabla        Pattern_of_interest blabla
blabla                            blabla
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
                             >    Inserted_text
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
                             >    Inserted_text
blabla                            blabla
blabla                            blabla
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
如果你更喜欢在模式二之前有自己的兴趣模式: 。。。然后diff变成:

blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
Pattern_of_interest blabla        Pattern_of_interest blabla
blabla                            blabla
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
                             >    Inserted_text
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
blabla                            blabla
Pattern_one                       Pattern_one
blabla                            blabla
blabla                            blabla
                             >    Inserted_text
Pattern_two                       Pattern_two
blabla                            blabla
blabla                            blabla
另一种方法,无需将整个块存储在内存中 但这种方式意味着在块的末尾添加插入的文本:

sed -e '                 
    /Pattern_one/,/Pattern_two/{
      //{
         /one/h;
         /two/{
            x;
            /Pattern_of_interest/!iInserted_text
            x;
         };
      };
      /Pattern_of_interest/h;
}' -i file.txt

sed的另一种方法:

sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_one/s/\n/&Inserted_text\n/};P;D;}' file
Pattern\u one
Pattern\u two
之间的行添加到模式空间,如果块中找不到感兴趣的
Pattern\u
,请在
Pattern\u one
之后插入新文本

要在模式二之前插入文本,请执行以下操作:

sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_two/s/.*\n/&Inserted_text\n/};P;D;}' file
sed '/Pattern_one/!b;:a;N;/Pattern_two/!ba;/Pattern_of_interest/b;h;s/\n[^\n]*$//p;x;s/^.*\n//;iInserted text' file
这可能适用于您(GNU-sed):

使用
Pattern\u one
查找地址,否则按正常方式打印(无需进一步处理)

引入一个位置
:a
,并使用
N
命令将下一行追加到模式空间(PS)

检查PS是否包含地址
模式\u two
,如果不包含,则返回位置
:a
,然后重复

PS现在包含从
Pattern\u one
Pattern\u two
的所有行

检查PS,查看它是否包含感兴趣的
图案
,以及它是否爆发
b
,并正常打印,在此循环中不进行进一步处理

如果没有,请使用
h
命令将PS复制到保留空间(HS),然后使用替换命令
s/\n.*//p
,打印PS的第一行

使用命令
x
将HS替换为PS,并使用另一个替换命令
s/^[^\n]*\n/
准备PS以包含减去第一行的剩余行

现在使用
i
命令插入新文本

执行插入命令后,sed循环将打印PS中剩余的内容

用于在模式二之前插入文本:

sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_two/s/.*\n/&Inserted_text\n/};P;D;}' file
sed '/Pattern_one/!b;:a;N;/Pattern_two/!ba;/Pattern_of_interest/b;h;s/\n[^\n]*$//p;x;s/^.*\n//;iInserted text' file

除了末尾的两个替换命令外,它使用基本相同的代码首先打印PS中最后一行的所有行,然后在执行插入命令后将PS准备为仅包含最后一行。

我认为这更适合
awk
,你有这个命令吗?@Sundeep我经常使用block和underblock来研究和治疗!请看@F.Hauri,这只会强化我的观点,
awk
更适合。。。那个代码对我来说是希腊语,我过去曾试图理解它,但无法。。对我来说(对大多数其他人来说也是如此),将perl/awk与更常用的编程流程结合使用更容易@Sundeep:我同意你的观点,awk脚本更容易处理。通常,我依靠sed对存储在纯文本中的从头开始的数据提取进行预格式化,然后在插入字段和记录分隔符时使用awk处理文件。这样,您就无法选择将插入的文本放置在块的第一行。如果您不想将整个块存储在内存中,我添加了另一种方法,即无论如何使用块。@F.Hauri I edited。第一个命令是在
模式一
之后插入新文本,第二个命令是在
模式二
之前插入新文本。
sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_two/s/.*\n/&Inserted_text\n/};P;D;}' file
sed '/Pattern_one/!b;:a;N;/Pattern_two/!ba;/Pattern_of_interest/b;h;s/\n.*//p;x;s/^[^\n]*\n//;iInserted text' file
sed '/Pattern_one/!b;:a;N;/Pattern_two/!ba;/Pattern_of_interest/b;h;s/\n[^\n]*$//p;x;s/^.*\n//;iInserted text' file