当根本找不到值时插入包含值的新行

当根本找不到值时插入包含值的新行

我试图在这里找到一些我可以使用的先前问题,但不幸的是找不到我的确切案例。

我想从另一个命令的输出中获取如下所示的内容:

pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c

对此:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

我尝试多解释一下:在包含字符串“pattern”的每一行之后应该始终有一个数字。如果没有,我想插入一个值为 1000 的新行。

请注意,模式有一个变化的“扩展名”(.a .b .c .d 但不是“扩展名”中的数字),它将帮助我稍后按字母顺序对内容进行排序。

编辑:我已经接受了一个答案,但如果有人仍然想寻找另一种变体,我应该指定“模式”的出现有所不同,并且可能有超过 2 或 3 个连续的,例如:

pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91

答案1

这是一个sed适用于任何输入的解决方案(例如匹配的多个连续行pattern):

sed '1{                   # when on first line
x                         # exchange
s/^/1000/                 # replace the empty hold buffer with "1000"
x                         # exchange back
}
: do                      # label "do"
/pattern/{                # if the current line matches "pattern"
${                        # if we're on the last line
G                         # append hold buffer content to pattern space
b                         # go to end of script
}
n                         # otherwise print and pull in the next line
/^[[:digit:]]/!{          # if this one doesn't start with a digit
x                         # exchange
p                         # print (the pattern space is now "1000")
x                         # exchange back
b do                      # go to label "do"
}
}' infile

有了gnu sed它就可以写成

sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile

您可以执行类似的操作awk

awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile

也就是说,c=1在匹配的行上设置patternc=0在其余行上设置,在不以数字开头的每一行上设置(以及在块中END)检查是否c已设置(或1- 意味着上一行匹配pattern) - 如果是打印1000

答案2

sed -e '
   $!{
      /pattern\.[a-z]/N
      /\n/!b
      /\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
      /\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
      h;s/\(.*\n\).*/\11000/p
      g;D
   }
   /pattern\.[a-z]/a\
1000
' yourfile

结果

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

在职的

  • 虽然不在 eof 处,但$!{...}我们将下一行附加到模式空间,条件是当前行是感兴趣的行。
  • 然后,我们在以下情况下跳过任何进一步的处理:a) 未找到换行符 => 当前行中没有模式。 b) 第二行中的 .nnn 格式的浮点数。 c) 格式为 mmm、mmm. 或 mmm.nnn 的浮点数仅出现在第二行。 d) 排除任何可能性 => 我们需要将幻数 1000 添加到换行符之后的下一行末尾。

答案3

如果 的连续实例绝不会超过两个pattern,并且您有 GNU sed,那么:

sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

怎么运行的:

  • 如果当前行以patternthen 开头
    • 如果我们不在 EOF,请附加下一行
    • 如果换行符后面有一个数字(可以更具体),则b退出(即继续到下一行);别的
    • 替换以换行符结尾的第一行并1000

GNU 特定的M修饰符允许$匹配 or \n$以便它处理“正常”情况和 EOF 情况(不附加后续行)。

答案4

awk解决方案:

awk '{ if ($0 ~ /pattern/) {      # if it's a `pattern` line
         if ((getline nl) > 0) {  # check if next record exists
             # if next record hasn't number - insert `1000`, otherwise - print current and next records as they are
             print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
         } else {
             print $0 ORS 1000   # if the file ends up with pattern - insert `1000`
         } 
       } else {
          print $0  # print other record
       }
    }' file

输出:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

相关内容