我发现了这个问题,它解决了我 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)
)
答案4
这是一个 sed 解决方案:
$ sed -n '/=A/,/^)/p' infile | sed '/=A/i ('
(
Device=A
Data=asdfasdf(aewf)
Lorem=Ipsum
)
(
Device=A
Data=asdfasdf(jalks)
)