【问题标题】:Join certain lines with sed用 sed 加入某些行
【发布时间】:2019-01-22 11:40:44
【问题描述】:

我有一个如下所示的输入:

1
2

3
4
5

6

我想用 sed 将其转换为:

12
345
6

我知道它可以使用其他工具轻松完成,但我想专门使用 sed 作为学习练习来完成它。 我已经尝试过:

sed ':x ; /^ *$/{ N; s/\n// ; bx; }'

但它会打印:

123456

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 可能是这样的:s/\n([^\n])/\1/?
  • wrt I want to do it specifically with sed as a learning exercise - 一个令人钦佩的目标,但你将学习如何做一些你永远不应该做的事情,那么重点是什么?
  • 是的,但是 sed 唯一最适合的就是 s/old/new 在单独的行上,你不需要很多经验来学习如何做到这一点。大约 40 年前,所有用于执行其他任何操作(例如 this)的 sed 语言结构实际上已经过时了。那么,为什么不学习简单、健壮、高效、可移植、可维护的方法来使用标准 UNIX 工具完成所有工作,而不是学习如何编写神秘的 sed 脚本,如果你把分号放在错误的位置,可能会调用黑暗之神 Cthulu?
  • @EdMorton 哈哈哈。我必须承认我笑了。这只是自我提升的问题。 Sed 语法笨拙且过时(如 Perl),但即使出于历史原因,也值得学习。
  • 是的,我想我们都对金字塔是如何建造的很感兴趣,但这并不意味着任何人很快就会在他们的后院建造金字塔。只要你没有真正发现自己在你的真实软件中使用它,我想知道一些 sed 咒语没有什么坏处......

标签: sed


【解决方案1】:

引用GNU sed manual:

处理段落等文本块(而不是逐行)的常用技术是使用以下结构:

sed '/./{H;$!d} ; x ; s/REGEXP/REPLACEMENT/'
  1. 第一个表达式/./{H;$!d} 对所有非空行进行操作,并将当前行(在模式空间中)添加到保持空间。在除最后一行之外的所有行上,模式空间都被删除并重新开始循环。

  2. 其他表达式 xs 仅在空行(即段落分隔符)上执行。 x 命令将累积的行从保持空间取回模式空间。然后s/// 命令对段落中的所有文本(包括嵌入的换行符)进行操作。

确实,

sed '/./{H;$!d} ; x ; s/\n//g'

做你想做的。

【讨论】:

    【解决方案2】:

    FWIW 下面是在 UNIX 中真正完成该任务的方法:

    $ awk -v RS= -v OFS= '{$1=$1}1' file
    12
    345
    6
    

    以上内容适用于任何 UNIX 机器。

    【讨论】:

      【解决方案3】:

      GNU awk 方法:

      $ awk -F"\n" '{gsub("\n","");}1' RS='\n{2,}' file
      12
      345
      6
      

      注意它会在最后一行之后添加一个尾随换行符\n

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-29
        • 2016-04-27
        • 2016-12-25
        • 2020-10-27
        • 1970-01-01
        • 2015-01-05
        • 2021-02-13
        相关资源
        最近更新 更多