使用 sed 重复打印一行中重复 n 次的模式

使用 sed 重复打印一行中重复 n 次的模式

使用sedcmd,我想在一行中打印所有出现的模式。我知道如何使用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/ … /匹配项,因此返回所需的三个匹配项。

https://docs.raku.org/language/regexes
https://raku.org

相关内容