首页 > 解决方案 > 在 d(elete)、a(pend) 或 c(hange) 之后,SED 不处理 {} 中的多个命令

问题描述

sed应该在匹配模式的多个命令之后处理,这些命令在{cmd1;cmd2;cmd3} 等大括号中给出。但是在下面给定的代码中,d(elite) 之后的所有命令都将被忽略。

脚本.sed

s/^\(interface GigabitEthernet0\)$/\1\/0/
/interface GigabitEthernet0\/0$/{
n       # process next line = 1st line (after match) to be deleted
d       # Should delete '1st line (after match) to be deleted'
n       # process next line = 2nd line to be altered
s/2nd line to be altered/2ND LINE AFTER ALTERATION/
n
s/3rd line to be altered/3RD LINE AFTER ALTERATION/
}

输入.txt

interface GigabitEthernet0
  1st line (after match) to be deleted
  2nd line to be altered
  3rd line to be altered
  4th line stays unchanged

sed -i -f script.sed example.txt

预期输出:

interface GigabitEthernet0/0
  2ND LINE AFTER ALTERATION
  3RD LINE AFTER ALTERATION
  4th line stays unchanged

有效输出:

interface GigabitEthernet0/0
  2nd line to be altered
  3rd line to be altered
  4th line stays unchanged

如上面的输出所示,要删除的第 1 行(匹配后)已被有效删除。但是以下所有行(第 2、第 3、第 4 行)都不会被替换。

顺便说一句:像 a(pend) 或 c(hange) 这样的命令的行为方式相同;所有后续命令都将被忽略。

标签: awksed

解决方案


sed 用于做 s/old/new,仅此而已。只需使用 awk,例如使用 GNU awk 进行就地编辑(就像您使用 GNU sed 一样)和 switch 语句:

$ cat tst.awk
/^interface GigabitEthernet0$/ { lineNr=1 }
lineNr%5 {
    switch (lineNr++) {
    case 1: $0 = $0 "/0";               break
    case 2: next;                       break
    case 3: sub(/2nd line/,"WHATEVER"); break
    case 4: $0 = toupper($0);           break
    }
}
{ print }

$ cat file
interface GigabitEthernet0
  1st line (after match) to be deleted
  2nd line to be altered
  3rd line to be altered
  4th line stays unchanged

$ awk -i inplace -f tst.awk file

$ cat file
interface GigabitEthernet0/0
  WHATEVER to be altered
  3RD LINE TO BE ALTERED
  4th line stays unchanged

并且以防万一您真的只想在匹配正则表达式后打印新行而不是修改范围内的现有行(例如在@AlexHarvey的 sed 答案中),那就是:

awk '/interface GigabitEthernet0/ {
    print $0 "/0\n  2ND LINE AFTER ALTERATION\n  3RD LINE AFTER ALTERATION"
    c = 4
}
!(c&&c--)' file
interface GigabitEthernet0/0
  2ND LINE AFTER ALTERATION
  3RD LINE AFTER ALTERATION
  4th line stays unchanged

请参阅https://stackoverflow.com/a/17914105/1745001上的常见 awk 习语列表,了解其c&&c--作用。

请注意,您不必多次指定初始正则表达式,您不必担心替换文本中可能会显示哪些字符,并且您只需给出一个数字,说明您不受影响的行数需要写相同的字符的次数。


推荐阅读