【问题标题】:With sed, how to add a text between 2 patterns when another pattern is not found inside them?使用 sed,当在其中找不到另一个模式时,如何在两个模式之间添加文本?
【发布时间】:2018-01-02 20:06:47
【问题描述】:

使用 sed,当在其中找不到另一个模式(这里是 Pattern_of_interest)时,如何在两个模式(这里是 Pattern_one 和 Pattern_two)之间添加一个文本(这里是 Inserted_text)?

在我的文件中,end of line 字符只是一个 \n(即 Unix 格式),但我使用 GNU sed 版本 4.0.7 在 msdos 下工作。

我试过但没用的命令:

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、Pattern_one 旁边插入):

blabla
blabla
Pattern_one
Pattern_of_interest blabla
blabla
Pattern_two
blabla
blabla
blabla
blabla
Pattern_one
Inserted_text
Pattern_two
blabla
blabla
blabla
Pattern_one
Inserted_text
blabla
blabla
Pattern_two
blabla
blabla

所需的输出文件(在底部、iow、Pattern_two 旁边插入):

blabla
blabla
Pattern_one
Pattern_of_interest blabla
blabla
Pattern_two
blabla
blabla
blabla
blabla
Pattern_one
Inserted_text
Pattern_two
blabla
blabla
blabla
Pattern_one
blabla
blabla
Inserted_text
Pattern_two
blabla
blabla

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

【问题讨论】:

  • 我觉得这个更适合awk,你有那个命令吗?
  • @Sundeep 我经常使用block和under-block研究和治疗使用sed!见my answer
  • @F.Hauri 这只会强化我的观点,即awk 更适合...该代码对我来说是希腊语,我过去曾试图理解它但无法理解。 . 并且使用 perl/awk 和更常用的编程流程对我来说更容易(对于大多数其他人来说也是 imo)
  • @Sundeep :我同意你的观点,即 awk 脚本更易于处理。通常,我依靠 sed 从头开始​​格式化以纯文本形式存储的数据提取,然后在插入字段和记录分隔符后使用 awk 处理文件。

标签: sed


【解决方案1】:

这可能对你有用(GNU sed):

sed '/Pattern_one/!b;:a;N;/Pattern_two/!ba;/Pattern_of_interest/b;h;s/\n.*//p;x;s/^[^\n]*\n//;iInserted text' file

使用Pattern_one 查找地址,否则正常打印(无需进一步处理)。

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

检查 PS 是否包含地址 Pattern_two,如果没有则循环回位置 :a 并重复。

PS 现在包含从Pattern_one 到Pattern_two 的所有行。

检查 PS 以查看它是否包含 Pattern_of_interest 以及它是否打破了 b 并正常打印,在此循环中不进行进一步处理。

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

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

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

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

用于在Pattern_two之前插入文本:

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 以仅包含最后一行。

【讨论】:

    【解决方案2】:

    使用 sed 的另一种方法:

    sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_one/s/\n/&Inserted_text\n/};P;D;}' file
    

    Pattern_one 和 Pattern_two 之间的行被添加到模式空间中,如果在块中找不到 Pattern_of_interest,则在 Pattern_one 之后插入新文本。

    在Pattern_two之前插入文本:

    sed '/Pattern_one/{:a;N;/Pattern_two/!ba;/Pattern_of_interest/! {/Pattern_two/s/.*\n/&Inserted_text\n/};P;D;}' file
    

    【讨论】:

    • 这样,您不能选择将 插入的文本 放置在块的第一行。如果您不将整个块存储在内存中,我添加了另一种方法,即无论如何都使用块。
    • @F.Hauri 我编辑了。第一个在Pattern_one 之后插入新文本的命令,第二个在Pattern_two 之前插入的命令。
    【解决方案3】:

    就是这样:

    sed -e '
        /Pattern_one/,/Pattern_two/{
          //{
             /one/h;
             /two/{
                H;
                x;
                /Pattern_of_interest/!s/\n/\nInserted_text\n/;
                p;
             };
             d;
          };
        //!H;
        d;
    }' -i file.txt
    

    还有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
    

    如果您更喜欢在模式二之前有您的感兴趣的模式:

    sed -e '                 
        /Pattern_one/,/Pattern_two/{
          //{
             /one/h;
             /two/{
                H;
                x;
                /Pattern_of_interest/!s/\nPattern_two/\nInserted_text&/;
                p;
             };
             d;
          };
        //!H;
        d;
    }' -i file.txt
    

    ...然后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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多