使用sed删除两个匹配模式之间的所有行

Ken*_*Ken 57 regex sed

我有一个类似的文件:

# ID 1
blah blah
blah blah
$ description 1
blah blah
# ID 2
blah
$ description 2
blah blah
blah blah
Run Code Online (Sandbox Code Playgroud)

如何使用sed命令删除#$线之间的所有行?结果将变为:

# ID 1
$ description 1
blah blah
# ID 2
$ description 2
blah blah
blah blah
Run Code Online (Sandbox Code Playgroud)

能不能请你解释一下吗?

anu*_*ava 50

使用此sed命令来实现:

sed '/^#/,/^\$/{/^#/!{/^\$/!d}}' file.txt
Run Code Online (Sandbox Code Playgroud)

Mac用户(为防止extra characters at the end of d command错误)需要在结束括号之前添加分号

sed '/^#/,/^\$/{/^#/!{/^\$/!d;};}' file.txt
Run Code Online (Sandbox Code Playgroud)

OUTPUT

# ID 1
$ description 1
blah blah
# ID 2
$ description 2
blah blah
blah blah
Run Code Online (Sandbox Code Playgroud)

说明:

  • /^#/,/^\$/将匹配从#以#开头的行之间的所有文本匹配$.^用于行字符的开头.$是一个特殊的角色,所以需要逃脱.
  • /^#/! 意味着如果没有开始行则执行以下操作 #
  • /^$/! 意味着如果没有开始行则执行以下操作 $
  • d 意味着删除

所以,总体来说它是第一个匹配的所有行从^#^\$然后从那些符合条件的行发现,行不匹配 ^#不匹配 ^\$,并使用删除它们d.

  • 对于Mac用户:为了防止在d命令结束时出现'额外字符'错误,你需要在结束括号之前添加分号`sed'/ ^#/,/ ^\$/{/ ^#/!{/ ^\$ /!d;};}'file.txt` (14认同)
  • 这就是投反对票的理由吗?如果您喜欢某个答案,请投票。投反对票通常是针对某些无法解决OP问题的答案,并且由于OP已经接受了这个答案,这意味着它对OP有效。不是吗? (5认同)
  • 然后只需使用: `sed '/^#/,/^\$/d' file` (3认同)

Lri*_*Lri 37

$ cat test
1
start
2
end
3
$ sed -n '1,/start/p;/end/,$p' test
1
start
end
3
$ sed '/start/,/end/d' test
1
3
Run Code Online (Sandbox Code Playgroud)

  • 它处理 300mb 文件的速度令人印象深刻。我说的是 SSD 上的一瞬间。 (2认同)
  • 由于我不熟悉 sed 语法,我有点困惑。目前尚不清楚第一个和第二个 sed 命令是否没有依赖性 - 即两者之间的区别在于您是否要保留匹配标记。在我测试它之前,我假设第一个命令删除了令牌之间的所有内容,第二个命令删除了令牌本身。如果您尝试删除标记之间的块,则只需使用第二个命令。 (2认同)
  • 实际有效的解决方案如下: `sed '/PATTERN-1/,/PATTERN-2/{//!d}' input.txt` (2认同)

fbi*_*nel 12

一般来说,如果你的文件内容为abcde形式,其中a部分在模式b之前,那么c部分在模式d之前,然后是e部分,你应用以下sed命令,得到以下结果.

在此演示中,输出由表示=> abcde,其中字母显示哪些部分将在输出中.因此,ae仅显示部分ae的输出,ace将是部分a,ce等.

请注意,如果bd出现在输出中,那些是出现的模式(即,它们被视为输出中的部分).

也不要将/d/模式与命令混淆d.这些演示中的命令总是在最后.模式始终在//.

  • sed -n -e '/b/,/d/!p' abcde => ae
  • sed -n -e '/b/,/d/p' abcde => bcd
  • sed -n -e '/b/,/d/{//!p}' abcde => c
  • sed -n -e '/b/,/d/{//p}' abcde => bd
  • sed -e '/b/,/d/!d' abcde => bcd
  • sed -e '/b/,/d/d' abcde => ae
  • sed -e '/b/,/d/{//!d}' abcde => abde
  • sed -e '/b/,/d/{//d}' abcde =>王牌


Ric*_*mon 7

很久以前我做了类似的事情,它是这样的:

sed -n -e "1,/# ID 1/ p" -e "/\$ description 1/,$ p"
Run Code Online (Sandbox Code Playgroud)

类似于:

  • -n抑制所有输出
  • -e "1,/# ID 1/ p"从第一行开始执行,直到您的模式和 p(打印)
  • -e "/\$ description 1/,$ p"从第二个模式开始执行,直到结束并 p(打印)。

我可能对字符串上的一些转义有误,所以请仔细检查。


SLe*_*ort 5

sed的另一种方法:

sed '/^#/,/^\$/{//!d;};' file
Run Code Online (Sandbox Code Playgroud)
  • /^#/,/^\$/:从#以第一个开始的行到下一个以$
  • //!d:删除除匹配地址模式的行以外的所有行

  • 试试这个:`sed'/ ^#/,/ ^ \ $ / d;' 文件`。 (2认同)