给定一个这样的文件:
a foo 1
b bar 2
c foo 3
d baz 4
e bar 5
我想按如下方式修改该文件:将包含bar
以下行的每一行复制并更改bar
为bar2
,以便结果如下所示:
a foo 1
b bar 2
b bar2 2
c foo 3
d baz 4
e bar 5
e bar2 5
答案1
正如 Stéphane 所建议的,只需p
打印该行然后s
替换,sed
就会自动打印结果:
sed '/bar/{p;s//&2/;}' infile
答案2
使用任何 awk:
$ awk '1; sub(/bar/,"&2")' file
a foo 1
b bar 2
b bar2 2
c foo 3
d baz 4
e bar 5
e bar2 5
$ awk '1; sub(/bar/,"hello world")' file
a foo 1
b bar 2
b hello world 2
c foo 3
d baz 4
e bar 5
e hello world 5
打印该行(1
)然后尝试bar
用您喜欢的任何内容替换,如果成功(sub()
返回非零)再次打印现在修改的行。
答案3
答案4
使用乐(以前称为 Perl_6)
~$ raku -ne '.put; .put if s/bar/bar2/;' file
或者:
~$ raku -ne '.put; .subst(/bar/, "bar2").put if /bar/;' file
或者:
~$ raku -ne '.put; /bar/ && .subst(/bar/, "bar2").put;' file
Raku 是 Perl 家族的一种编程语言。它具有对内置 Unicode 的高级支持。上面,-ne
使用了非自动打印逐行标志,它将数据逐行加载到$_
Raku(和 Perl 的)主题变量中。因为 Raku 默认情况下会自动删除行,所以调用put
(而不是print
)会为您添加一个换行符(想象一下put
代表p林特-你唱歌-t终结者)。
Raku 通过要求给
put
/print
等一个明确的对象来减少歧义。因此.put
是 的缩写,$_.put
与 相同put $_
,表示将打印未修改的行。在第一个示例中,修改后的行添加了众所周知的
s///
替换符号。 (s:g///
此处用于全局替换)。在第二个示例中,
if
发现匹配subst
将发生,并且结果行将出现put
在下一行中。第三个示例几乎与第二个示例相同,只是它依赖于&&
短路。当 Raku 中发生匹配时,通常会将匹配加载到
$<>
变量中(与 相同$/
,但更易于阅读)。所以任务是“加一个2”可以用S/bar/$<>2/
或更简单地完成.subst(/bar/, "$<>2");
。
输入示例:
a foo 1
b bar 2
c foo 3
d baz 4
e bar 5
示例输出:
a foo 1
b bar 2
b bar2 2
c foo 3
d baz 4
e bar 5
e bar2 5
如果您正在使用一个特别复杂的正则表达式,那么上面的示例并不是那么干燥。但是您可以将匹配项保存到临时变量中以供进一步使用(例如$a
下面):
~$ raku -ne '.put; if m/complicated_pattern/ -> $a {S/<$a>/replacement/.put};' file
或者regex
从一开始就声明一个 -class 变量:
~$ raku -ne 'BEGIN my regex RE {complicated_pattern}; \
.put; .put if s/<RE>/replacement/; file
#OR
~$ raku -ne 'BEGIN my regex RE {complicated_pattern}; \
.put; .subst(/<RE>/, "replacement" ).put if /<RE>/;' file
#OR
~$ raku -ne 'BEGIN my regex RE {complicated_pattern}; \
.put; /<RE>/ && put .subst(/<RE>/, "replacement" );' file