从文件中删除一个字符串和另一个字符串及其后的所有内容

Remove from file a string and another string and everything after it

假设我有一个文件teams,内容如下:

[Desktop Entry]
Version=1.0
Type=Application
Name=Microsoft Teams - Preview
Comment=Microsoft Teams for Linux is your chat-centered workspace in Office 365.
Exec=teams %U
Icon=teams
Terminal=false
StartupNotify=true
StartupWMClass=Microsoft Teams - Preview
Categories=Network;
MimeType=x-scheme-handler/msteams;
X-KDE-Protocols=teams
Actions=QuitTeams;
X-GNOME-UsesNotifications=true;

[Desktop Action QuitTeams]
Name=Quit Teams

我想删除一行 Actions=QuitTeams;。这看起来很简单:

sed -i '/Actions=QuitTeams;/d' teams

此外,我想删除一行 [Desktop Action QuitTeams] 及其后的所有内容(可能会有新行)。 这看起来也很简单:

sed -i '/[Desktop Action QuitTeams]]/,$d' teams

我的问题是:如何在一次 sed 执行中完成这两个步骤,即将所有正则表达式合并为一个? Sed 是首选,但也欢迎使用其他工具。

您可以尝试使用 sed-e 选项(参见 3.8 Multiple commands syntax):

$ sed -i -e '/Actions=QuitTeams;/d' -e '/[Desktop Action QuitTeams]]/,$d' teams
$ cat teams
[Desktop Entry]
Version=1.0
Type=Application
Name=Microsoft Teams - Preview
Comment=Microsoft Teams for Linux is your chat-centered workspace in Office 365.
Exec=teams %U
Icon=teams
Terminal=false
StartupNotify=true
StartupWMClass=Microsoft Teams - Preview
Categories=Network;
MimeType=x-scheme-handler/msteams;
X-KDE-Protocols=teams
X-GNOME-UsesNotifications=true;

您正在按原样使用 -i 就地修改选项,因此您正在使用 GNU sed。在 GNU sed 中,您还可以使用

sed -z -i 's/[^\n]*Actions=QuitTeams;[^\n]*\n\?\|[^\n]*\[Desktop Action QuitTeams].*//g' teams

参见online demo

-z 选项忽略行尾,行尾对正则表达式“可见”。

sed 正则表达式是 POSIX BRE 兼容模式,匹配

  • [^\n]* - 除 LF
  • 之外的零个或多个字符
  • Actions=QuitTeams; - Actions=QuitTeams; 字符串
  • [^\n]*\n\? - 除 LF 之外的零个或多个字符,然后是可选的 LF 字符
  • \| - 运算符 OR
  • [^\n]* - 除 LF
  • 之外的零个或多个字符
  • \[Desktop Action QuitTeams] - [Desktop Action QuitTeams] 字符串(注意转义的 [ 以免定义括号表达式)
  • .* - 直到文件末尾的任何文本(因为 POSIX 正则表达式中的 . 匹配任何字符,包括换行字符)。