【问题标题】:write each block of text between two markers to a file with sed使用 sed 将两个标记之间的每个文本块写入文件
【发布时间】:2017-10-04 10:06:32
【问题描述】:

我想将STARTEND 标记之间的每个文本块提取到一个单独的文件中。 Sed 将是首选工具,但 grep 和 awk 也可以。

给定以下文件内容:

abc
START
  def
END
ghi
START
  jkl
END
mno

sed 应该分别用内容创建两个文件:

START
  def
END

START
  jkl
END

我知道如何用 sed 获取两个正则表达式之间的内容:

sed -n '/START/,/END/p'

当提供e 标志时,还有这个选项可以在 sed 中执行 shell 命令。可以利用它来完成这项任务吗?

【问题讨论】:

    标签: bash shell sed


    【解决方案1】:

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

    sed '/START/,/END/!d' file | csplit -z - '/END/1' '{*}'
    

    使用 sed 收集开始和结束分隔符之间的所有行,然后应用 csplit 为每组行创建单独的文件。

    【讨论】:

    • ++ ve 代码不错。感谢您提供非常好的代码,请您稍微解释一下 csplit 将不胜感激。
    • @RavinderSingh13 csplit 是拆分的变体。它需要一个文件和一些模式(必要时带有偏移量)。请参阅 info/man csplit 或 csplit -h。
    • 不错的方法,但为什么它会为示例生成 3 个文件?最后一个是空的,前两个是预期的。
    • @PeterLutz 哎呀!忘记 csplit 中的 -z 选项以防止空文件!
    【解决方案2】:

    awk 保存在这里:

    awk '/END/{flag="";print > i"_file";close(i"_file");next} /START/{flag=1;print > ++i"_file";next} flag{print > i"_file"}'  Input_file
    

    输出它将创建两个名为 1_file 和 2_file 的文件,内容如下。

    cat 1_file
    START
      def
    END
    
    cat 2_file
    START
      jkl
    END
    

    现在也添加非单线形式的解决方案。

    awk '
    /END/{
      flag="";
      print > i"_file";
      close(i"_file");
      next
    }
    /START/{
      flag=1;
      print > ++i"_file";
      next
    }
    flag{
      print > i"_file"
    }
    '   Input_file
    

    【讨论】:

      【解决方案3】:

      非常有趣的 csplit

      谢谢波东

      所以没有 sed

      csplit -z --suppress-matched infile %START%-1 /END/1 {*}
      

      -m = --suppress-matched 不起作用。

      manpage fr tell -m 但它是错误的。

      【讨论】:

      • 适用于示例,但如果 START 在第一行,它会抱怨行号超出范围
      • 你可以这样使用它 (echo;cat infile) | csplit - -z -s --suppress-matched %START%-1 /END/1 {*}
      猜你喜欢
      • 2014-11-13
      • 2020-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-25
      相关资源
      最近更新 更多