是否可以用sed匹配多个特定的行号(而不是范围)?


9

考虑:

echo -e "a\nb\nc\nd\ne\nf\ng\nh" | sed '3,5a test'

这将匹配第3、4和5行。

但我试图只匹配第3行和第5行(而不是第4行)。并在其后附加“测试”。

Answers:


9
echo ... | sed -e '3a test' -e '5a test'

如果操作比这种情况更复杂,则可以使用如下结构:

sed 'b pattern; : action; a \
lalala
b end; : pattern; 3b action; 5b action; : end'

也就是说,您将所需的所有命令放在b pattern;和之间b end;

然后在之后添加所有模式(行号或其他内容): pattern;

这是怎么回事:

  1. 第一个命令会跳过动作部分(如果模式位于b end;动作部分的开头和紧前面,则可能更容易阅读)。

  2. 如果模式匹配,则执行跳转到动作部分。动作部分执行后跳到最后。

我尝试整理一下:

sed '3b action; 5b action; b end; : action; a \
lalala
: end'

在一行中将是这样的:

sed "3b idAction; 5b idAction; b; : idAction; a test"

可移植地,您需要编写它:

sed '
   3b action
   5b action
   b
   : action
   a\
   lalala'

b没有标签的末尾分支,因此您不需要显式end标签,;在标准sed实现中,标签中的字符是有效的)。


4
哇,sed子程序。酷
格林·杰克曼(Glenn Jackman)2014年

哇,的确,您可以扩展这些吗?他们看起来真的很有用!
terdon

带有“模式”和“动作”的人看起来非常好,因为我不需要重复“测试”(或“拉拉拉”),因此请更好地理解它!:)
水瓶座力量

@terdon我能怎么办?
Hauke Laging

我的意思是第二个看起来不错,但很难理解,如果您有时间,我将不胜感激。
terdon

5

sed(请参阅@HaukeLaging的答案

awk

$ echo -e "a\nb\nc\nd\ne\nf\ng\nh" | awk 'NR==3 || NR==5{$0=$0"\ntest"}1;'

perl

$ echo -e "a\nb\nc\nd\ne\nf\ng\nh" | perl -pe '$_ .="test\n" if $. == 3 || $. == 5'

可以使用“智能匹配”运算符稍微打高尔夫:perl -lnE 'say if $. ~~ @{[3,5]}'
glenn jackman 2014年

@glennjackman啊,的确是,谢谢。我必须承认我有些警惕~~,对它的理解不如我应有的好。此外,无论是say~~需要的perl V> = 5.10吗?
terdon

我需要在那几行之后添加“测试”,我现在认为最好从一开始就澄清一下。我刚刚编辑了OP。
Aquarius Power

@AquariusPower,perl -pE 'say "test" if $. ~~ @{[4,6]}'-该预规划线路:Perl的-p执行一个隐含的打印在年底给定的程序。
glenn jackman 2014年

@AquariusPower也可以看到更新的答案。
terdon

3

就像@HaukeLaging aleady所说的,此命令可以执行您想要的操作:

sed -e'3a test' -e'5a test'

现在,如果要匹配(例如20行),则键入起来会很麻烦。

在这些情况下,假设您的外壳支持括号扩展,则可以改用以下命令:

sed -e{3,5}'a test'

(请注意,大括号和逗号必须不加引号。)

结果,shell将把参数传递给sed -e3a test并传递-e5a test给sed,这正是第一个命令的作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.