【问题标题】:sed delete between two patterns deletes until end if second pattern is not found如果未找到第二个模式,则在两个模式之间删除 sed 直到结束
【发布时间】:2020-01-07 22:03:39
【问题描述】:

我正在使用sed 删除配置文件中的标签,但我无意中发现了一个问题,我将使用一个基本示例:

numbers.txt 文件内容:

0
1
2
3
4
5
6
7
8
9

在两个数字之间删除(包括数字本身):

sed '/4/,/6/d' numbers.txt

产量(如预期):

0
1
2
3
7
8
9

但是,如果我从 numbers.txt 中删除 6 行,我希望相同的命令产生 all of numbers.txt,因为它找不到第二个模式,而是简单地删除4 行之后的所有内容(可能是因为搜索 6 到达了文件末尾,所以这就是它返回的值):

0
1
2
3

我的问题是:我如何修改sed 语句以在这种情况下不做任何事情?

【问题讨论】:

  • 为什么会这样?您看到的行为并不特别出人意料。
  • 这不是在我研究了 sed 的内部流控制如何工作之后,如果您熟悉它,我可以看到您会怎么想,但我将语法解释为“查找范围以 '4' 开头并以 '6' 结尾,然后删除行”

标签: sed


【解决方案1】:

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

sed '/4/{:a;$!{N;/6/Md;ba}}' file

建立自己的循环,只有满足结束条件时才删除模式空间中的累积行。

注意结束条件上的 M 标志允许在模式空间中收集的多行上进行匹配。

/start/,/end/d 是一个控制结构,在找到start 时会立即删除行,直到end 或文件末尾。因此有两个结束条件,地址/end/$。由于动作(在这种情况下删除)是立即的,如果不满足/end/ 条件,则无法撤消,因此需要根据两个条件之一收集和删除要删除的行, /end/(删除)或$(不要删除)。

  • /4/{...} 大括号内操作的起始地址。
  • :a 一个名为a 的循环的开始地址
  • $!{...} 如果不是大括号内的文件操作结束。
  • N 将换行符和下一行添加到模式空间。
  • /6/Md 结束地址和删除命令(如果找到),即这将删除模式空间中由 N 命令附加的所有行。
  • ba goto 命令,中断到循环地址a。这使得循环机制能够继续直到两个条件之一/6/$

注意如果满足文件结束条件,则/4/{...} 结束并正常打印累积的行。

【讨论】:

  • 有效,但我不知道为什么。请您详细说明语法吗?
  • 太好了,谢谢。我尝试在 sed 中查找有关 {...;...;...} 语法的信息(我认为这是 GNU sed 特有的),但遇到了困难。你知道一个很好的资源吗?另外,我读到这种类型的前瞻多行处理不适合像 sed 这样的流工具。有没有更合适的基础工具?
  • @robbie9485 点击sed 标签并查找链接learn more
  • Grymoire's Sed Tutorialsed 的深入了解非常好。祝你好运。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多