命令:

命令:

该块始终以:00 PROGRAM 开头

它以 XYZ 结尾,后跟一个空行。 XYZ 也出现在较早的行块中,但较早的行后面跟着更多数据。我只需要空行之前的最后一行。我还没有找到任何符合我意图的代码。我希望这对某人来说是一个简单的答案!

我确实想保留空白行之前的最后一行。例如:

000-12-22
AB1
00   PROGRAM
01   INQUIRY
03   XYZ
04   XYZ
blank line
LINE VALUE
00456

仅应删除这部分。

00   PROGRAM
01   INQUIRY
03   XYZ

答案1

这种类型的范围是完美的的用例ex 我有写了ex很多在本网站上;它无疑是用于脚本文件编辑的最佳 POSIX 工具。

命令:

如果您只需要处理一个块,请使用:

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

如果可能有多个块,请使用:

printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' x | ex file.txt

为了进行测试,请使用%p而不是x

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' %p | ex file.txt
printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' %p | ex file.txt

这将打印整个缓冲区,而不是将缓冲区的内容保存回文件。


插图:

[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 
[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ 

解释和评论:

您可以使用ex -c 'editingcommands' filename,但我发现这会产生比解决的问题更多的问题:如果遇到错误,ex不会退出,而是会挂起等待用户输入。此外,以这种方式传递多个命令还存在潜在的可移植性问题ex,因为 POSIX 不保证允许您这样做的常见功能。

相反,我通常将命令通过管道传输到exfrom printf。这允许通过使用%s\n格式字符串来轻松地换行分隔多个命令printf,并且如果出现错误,它会使文件保持不变,而不会挂起(例如,如果您尝试编辑大于文件最后一行的行)。

为了在实际编辑文件之前测试命令,我使用%p(打印整个缓冲区)作为最后一个命令。然后我可以稍微调整命令并一次又一次运行它,直到获得我想要的确切文件内容。一旦我对结果感到满意,我就会将其更改%px运行命令有更多时间来实际保存对文件的更改。

这又是我为回答这个问题而给出的命令:

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

printf命令只是打印三个字符串/00 PROGRAM/.,/^$/-2dx用换行符分隔,如下所示:

[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x
/00 PROGRAM/
.,/^$/-2d
x
[vagrant@localhost ~]$ 

这三行是ex命令。

ex命令概述

命令ex有两部分:地址(基于行)和命令。

如果只有一个地址,则光标将移动到该地址(移动到该行)。

如果只有命令,则使用当前行作为地址。

地址通常可以是范围— 一个地址,后跟一个逗号,然后是另一个地址。这是指从第一个地址到第二个地址的所有行。

地址可以是行号,但不一定是。它也可以是一个搜索模式,意思是“当前行之后与该正则表达式匹配的下一行”。您可以进行向后搜索以及向前搜索。

您甚至可以编写一个地址,表示“该实例之前的两行发生在最紧邻当前行之前foo的实例之后”。bar这看起来像:?bar?/foo/-2

一步步

该命令/00 PROGRAM/只是一个地址,因此它的意思是“将光标移动到模式‘00 PROGRAM’的第一个实例”。

该命令.,/^$/-2d有两个部分。最后d的 是命令,意思是“删除”。剩下的就是地址了。

首字母.是一个特殊的地址,引用当前行。

该模式/^$/是空行的正则表达式(行首^紧跟行尾$)。在这种情况下,它意味着当前光标位置之后的下一个空行。

意思-2是“向后两行”。

那么,所有这些都.,/^$/-2d意味着:“删除从当前行到下一个空行上方两行的行。”

x简单地说,将缓冲区内容保存到文件并退出编辑器。


希望这个对你有帮助。 ex是一个非常强大的文本编辑工具。它是vi“可视化编辑器”的前身。所有命令也ex可以运行。vi

答案2

回答修改后的问题

让我们考虑这个测试文件;

$ cat File2
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456

尝试这个命令:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x; p; x;}' File2
000-12-22
AB1
04 XYZ

LINE VA

卢埃00456

回答原来的问题

如果我理解正确,您有一个包含多组留置权的文件,这些留置权以包含空行的行开头00 PROGRAM并以空行结束,并且如果包含XYZ.如果是这种情况,请尝试以下操作:

sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 

例子

考虑这个示例文件:

$ cat file
00 PROGRAM
some
XYZ discard this
data
XYZ keep this

other
00 PROGRAM
more
XYZ keep this also

end

这仅保留XYZ块中空行之前的行00 PROGRAM

$ sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 
XYZ keep this
XYZ keep this also

选择

也许,您希望保留组之外的所有行,并且如果匹配,还保留组的最后一个非空行XYZ。在这种情况下:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/!d}' file 
XYZ keep this
other
XYZ keep this also
end

相关内容