在 awk/sed/grep 中删除匹配的第 n 行直到空行

发布于 2024-10-08 06:49:16 字数 59 浏览 9 评论 0原文

我需要删除文件中从匹配到下一个空白行的第 n 个匹配行(即从第 n 个匹配开始的一大块空白行分隔文本)。

I need to delete the nth matching line in a file from the match up to the next blank line (i.e. one chunk of blank line delimited text starting with the nth match).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

喜爱纠缠 2024-10-15 06:49:16

这将删除以第四个空行开始和结束的空白行的文本块。它还删除那些分隔线。

sed -n '/^$/!{p;b};H;x;/^\(\n[^\n]*\)\{4\}/{:a;n;/^$/!ba;d};x;p' inputfile

更改第一个 /^$/ 以更改开始匹配。更改第二个即可更改最终匹配。

给定以下输入:

aaa
---
bbb
---
ccc
---
ddd delete me
eee delete me
===
fff
---
ggg

此版本的命令:

sed -n '/^---$/!{p;b};H;x;/^\(\n[^\n]*\)\{3\}/{:a;n;/^===$/!ba;d};x;p' inputfile

将给出以下结果:

aaa
---
bbb
---
ccc
fff
---
ggg

编辑:

我从 sed 命令中删除了无关的 b 指令多于。

这是一个带注释的版本:

sed -n '      # don't print by default
  /^---$/!{   # if the input line doesn't match the begin block marker
    p;        # print it
    b};       # branch to end of script and start processing next input line
  H;          # line matches begin mark, append to hold space
  x;          # swap pattern space and hold space
  /^\(\n[^\n]*\)\{3\}/{    # if what was in hold consists of 3 lines
                           # in other words, 3 copies of the begin marker
    :a;       # label a
    n;        # read the next line
    /^===$/!ba;    # if it's not the end of block marker, branch to :a
    d};       # otherwise, delete it, d branches to the end automatically
  x;          # swap pattern space and hold space
  p;          # print the line (it's outside the block we're looking for)
' inputfile   # end of script, name of input file

任何明确的模式都应该适用于开始和结束标记。它们可以相同或不同。

This will delete a chunk of text that starts and ends with a blank line starting with the fourth blank line. It also deletes those delimiting lines.

sed -n '/^$/!{p;b};H;x;/^\(\n[^\n]*\)\{4\}/{:a;n;/^$/!ba;d};x;p' inputfile

Change the first /^$/ to change the start match. Change the second one to change the end match.

Given this input:

aaa
---
bbb
---
ccc
---
ddd delete me
eee delete me
===
fff
---
ggg

This version of the command:

sed -n '/^---$/!{p;b};H;x;/^\(\n[^\n]*\)\{3\}/{:a;n;/^===$/!ba;d};x;p' inputfile

would give this as the result:

aaa
---
bbb
---
ccc
fff
---
ggg

Edit:

I removed an extraneous b instruction from the sed commands above.

Here's a commented version:

sed -n '      # don't print by default
  /^---$/!{   # if the input line doesn't match the begin block marker
    p;        # print it
    b};       # branch to end of script and start processing next input line
  H;          # line matches begin mark, append to hold space
  x;          # swap pattern space and hold space
  /^\(\n[^\n]*\)\{3\}/{    # if what was in hold consists of 3 lines
                           # in other words, 3 copies of the begin marker
    :a;       # label a
    n;        # read the next line
    /^===$/!ba;    # if it's not the end of block marker, branch to :a
    d};       # otherwise, delete it, d branches to the end automatically
  x;          # swap pattern space and hold space
  p;          # print the line (it's outside the block we're looking for)
' inputfile   # end of script, name of input file

Any unambiguous pattern should work for the begin and end markers. They can be the same or different.

纵山崖 2024-10-15 06:49:16
perl -00 -pe 'if (/pattern/) {++$count == $n and $_ = "\n";}' file

-00 是以“段落”模式读取文件(记录分隔符是一个或多个空行)

$` 是 Perl 的“预匹配”特殊变量(文本在匹配模式的前面)

perl -00 -pe 'if (/pattern/) {++$count == $n and $_ = "\n";}' file

-00 is to read the file in "paragraph" mode (record separator is one or more blank lines)

$` is Perl's special variable for the "prematch" (text in front of the matching pattern)

囍笑 2024-10-15 06:49:16

在 AWK

/m1/  {i++};

(i==3)  {while (getline temp > 0 && temp != "" ){}; if (temp == "") {i++;next}};

{print}  

中将其转换

m1 1
first

m1 2
second

m1 3
third delete me!

m1 4
fourth

m1 5
last

m1 1
first

m1 2
second

m1 4
fourth

m1 5
last  

:删除“m1”的第三个块...

在此处在 ideone 上运行

哈!

In AWK

/m1/  {i++};

(i==3)  {while (getline temp > 0 && temp != "" ){}; if (temp == "") {i++;next}};

{print}  

Transforms this:

m1 1
first

m1 2
second

m1 3
third delete me!

m1 4
fourth

m1 5
last

into this:

m1 1
first

m1 2
second

m1 4
fourth

m1 5
last  

deleting the third block of "m1" ...

Running on ideone here

HTH!

夏九 2024-10-15 06:49:16

强制性 awk 脚本。只需将 n=2 更改为您的第 n 个匹配项即可。

n=2; awk -v n=$n '/^HEADER$/{++i==n && ++flag} !flag; /^$/&&flag{flag=0}' ./file

输入

$ cat ./file
HEADER
line1a
line2a
line3a

HEADER
line1b
line2b
line3b

HEADER
line1c
line2c
line3c

HEADER
line1d
line2d
line3d

输出

$ n=2; awk -v n=$n '/^HEADER$/{++i==n&&++flag} !flag; /^$/&&flag{flag=0}' ./file
HEADER
line1a
line2a
line3a

HEADER
line1c
line2c
line3c

HEADER
line1d
line2d
line3d

Obligatory awk script. Just change n=2 to whatever your nth match should be.

n=2; awk -v n=$n '/^HEADER$/{++i==n && ++flag} !flag; /^$/&&flag{flag=0}' ./file

Input

$ cat ./file
HEADER
line1a
line2a
line3a

HEADER
line1b
line2b
line3b

HEADER
line1c
line2c
line3c

HEADER
line1d
line2d
line3d

Output

$ n=2; awk -v n=$n '/^HEADER$/{++i==n&&++flag} !flag; /^$/&&flag{flag=0}' ./file
HEADER
line1a
line2a
line3a

HEADER
line1c
line2c
line3c

HEADER
line1d
line2d
line3d
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文