sed - 如果一行与 ^ 的条件匹配,则打印与模式范围匹配的行

sed - 如果一行与 ^ 的条件匹配,则打印与模式范围匹配的行

我发现了这个问题,它解决了我 99% 的问题,但我无法弄清楚将结束模式与^. sed - 如果一行与条件匹配,则打印与模式范围匹配的行

这是我的数据,它要求我匹配行开头的右括号。


(
Device=B
Data=asdfasdf(qwfw)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=B
Data=asdfasdf(wef)
)
(
Device=A
Data=asdfasdf(jalks)
)
(
Device=B
Data=asdfasdf(asf)
)
(
Device=C
Data=asdfasdf(asfew)
Lorem=Ipsum
)

我正在尝试这个命令,但它无法匹配任何内容。

sed -n '/(/{:a;N;/^)/!ba;/Device=A/p}' file

如果我删除^,它会返回这个

-> % sed -n '/(/{:a;N;/)/!ba;/Device=A/p}'  test 
(
Device=A
Data=asdfasdf(aewf)
(
Device=A
Data=asdfasdf(jalks)

有谁知道我在这里缺少什么?

sed版本

sed (GNU sed) 4.5
Copyright (C) 2018 Free Software Foundation, Inc.

答案1

当您在模式空间中累积行时,您不能再使用^ 来匹配后续行的开头,而必须使用\n(嵌入换行符):

sed -n '/(/{:a;N;/\n)/!ba; /Device=A/p}' infile

虽然我非常喜欢科斯塔斯的解决方案在那里(使用保持缓冲区通常更容易/更好):

sed 'H;/^(/h;/^)/!d;x;/Device=A/!d' infile

在这种情况下,^两种模式都需要锚点。

答案2

当尝试使用 sed 执行此操作时,您使用的是神秘的结构,这些结构在半个世纪前 awk 发明时就已经过时了。使用 GNU awk 实现多字符 RS 和 RT:

$ awk -v RS='\n)\n' '/Device=A/{ORS=RT; print}' file
(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(jalks)
)

或使用任何 awk:

$ awk '{r=r $0 ORS} /^)/{if (r ~ /Device=A/) printf "%s", r; r=""}' file
(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(jalks)
)

答案3

使用(以前称为 Perl_6

~$ raku -e '.put for slurp.comb( /^^ \( \n "Device=A" \n [\N+ \n]+? \) $$ / );'  file

#OR

~$ raku -e '.put for slurp.comb: /^^ \( \n "Device=A" \n [\N+ \n]+? \) $$ / ;'  file

comb简而言之,Raku 具有与 完全相反的功能split。您可以提供comb一个正则表达式匹配器,它会提取匹配的元素。

上面的代码slurp将文件放入(一次读入所有行),而不自动剪切每一行。要提取Device=A元素,只需列出所需的匹配行(包括\n仍然存在的换行符)。

注意:分组是一个或多个非换行符后跟换行符[\N+ \n]+?的非贪婪序列,此...分组模式非贪婪地出现一次或多次。\N\n[]+?

示例输出:

(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(jalks)
)

https://raku.org

答案4

这是一个 sed 解决方案:

$ sed -n '/=A/,/^)/p' infile | sed '/=A/i ('

(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(jalks)
)

相关内容