使用sed
cmd,我想在一行中打印所有出现的模式。我知道如何使用grep -Pe
和 来做到这一点awk
。我开始于:
$ sed 's/^.*label="\(.*\)" selected.*$/\1/g' <(echo 'smkj sld/6_ !label="snd 1" selected>lms slks.;label="snd 2" selected>lkwnl wlkmlabel="snd 3" selected>The following should not be printedlabel="')
snd 3
然而上面只打印snd 3
,即之间的字符串最后的label="
和的发生" selected
。如何在任意一行中包含所有出现的正则表达式?
答案1
使用GNU sed
我们可以生成所需的输出,如下所示:
$ sed -Ee '
s/label="([^"]+)" selected[>]/\n\1\n/
s/.*\n(.*\n)/\1/
/\n/!d
P;D
' input.txt
输出:
snd 1
snd 2
snd 3
您Perl
可以将其作为一个衬垫来完成:
$ perl -lne 'print for /label="([^"]+)" selected[>]/g' input.txt
答案2
使用乐(以前称为 Perl_6)
~$ raku -ne '$/.join("\n").put if m:g/ label\= \" <(<-["]>+)> \" \h selected \> /;' <(printf 'smkj sld/6_ !label="snd 1" selected>lms slks.;label="snd 2" selected>lkwnl wlkmlabel="snd 3" selected>The following should not be printedlabel="')
snd 1
snd 2
snd 3
#OR
~$ raku -ne '$/.join("\n").put if m:g/ label\= \" <(<-[\c[QUOTATION MARK]]>+)> \" \h selected \> /;' <(printf 'smkj sld/6_ !label="snd 1" selected>lms slks.;label="snd 2" selected>lkwnl wlkmlabel="snd 3" selected>The following should not be printedlabel="')
snd 1
snd 2
snd 3
Raku 是 Perl 系列中的一种编程语言,这个答案旨在赞扬 @RakeshSharma 发布的优秀 Perl 答案。
简而言之,这个 Raku 答案采用与 @RakeshSharma 相同的方法:不要尝试使用“节俭与贪婪”匹配来解决问题,而是要认识到用引号引起来的目标字符串没有内部引号。因此(类似于@RakeshSharma),在 Raku 中你声明一个自定义消极的字符类<-["]>+
,转换为“连续的一个或多个字符没有"
引号字符。 (如果您想知道,<+[…]>
或者更简单地<[…]>
表示自定义积极的字符类)。第二个答案明确使用规范\c[QUOTATION MARK]
名称,这有时可以帮助规避棘手的引用问题。
那么正则表达式的其余部分如下:
- 所需的匹配前面是
label\= \"
- 所需的匹配后面跟着
\" \h selected \>
(\h
代表水平空白)。 - 整个正则表达式匹配后,Raku 的
<( … )>
捕获标记把所有东西都扔到外面。
Raku 的$/
变量包含最终匹配项,并且由于指定了m:global/ … /
orm:g/ … /
匹配项,因此返回所需的三个匹配项。