增加源文件中的所有 defines/enums

Increment all defines/enums in a source file

假设我有很多 (100+) defines/enumerations/variables 例如:

FOO:    1
BAR:    2
QUX:    3
// ...
ZYX:   99
XYZ:  100

我想在 BAR 之后添加一个新行:BAZ: 3,并将 QUX 的值更新为“4”,并更新其余值。使用 built-in/native unix 文本编辑工具(如文本编辑器、sed 等)在 BAZ 之后递增所有值的最有效、最简单的解决方案是什么?

考虑这个输入文件:

$ cat file
FOO:    1
BAR:    2
QUX:    3
// ...
ZYX:   99
XYZ:  100

这会在 BAR 之后插入 BAZ 并递增之后的每个数字:

$ awk 'NR==1,/^BAR:/{print;next} !f{print "BAZ: 3";f=1} /^[[:alnum:]]+:/{print ,++;next} 1' file
FOO:    1
BAR:    2
BAZ: 3
QUX: 4
// ...
ZYX: 100
XYZ: 101

工作原理

  • NR==1,/^BAR:/{print;next}

    打印所有行,包括以 BAR: 开头的第一行,然后跳转到下一行

  • !f{print "BAZ: 3";f=1}

    我们只有在遇到 BAR 之后才会到达这一行。在这里,添加 BAZ 行并将标志 f 设置为 1,以便我们知道不再添加它。

  • /^[[:alnum:]]+:/{print ,++;next}

    对于以标识符后跟冒号开头的任何行,递增冒号后的数字并跳到下一行。

  • 1

    对于所有其他行,例如 //...,按原样打印它们。 (1 是 awk 的神秘 shorthand,用于按原样打印该行。)

awk 似乎最简单:

awk '{  += n; print }  == "BAR:" { n = 1; print "BAZ:",  + 1 }' filename

这里解读如下:

{                       # for all lines:
   += n               # increase second field by remembered number
                        # (initially 0)
  print                 # print line with that change
}
 == "BAR:" {          # When the first field in the line was "BAR:"
  n = 1                 # set offset
  print "BAZ:",  + 1  # insert new line
}

我假设整个文件只有一行BAR:;如果不能保证这一点,您可能需要将其修改为

awk '{  += n; print } !n &&  == "BAR:" { n = 1; print "BAZ:",  + 1 }' filename

只在第一个 BAR: 之后插入 BAZ: 行,或者

awk '{  += n; print }  == "BAR:" { ++n; print "BAZ:",  + n }' filename

在每次出现 BAR: 后插入 BAZ: 行,同时保持编号不变。当然,这两种变体都适用于简单的输入。

为了漂亮的格式化,您可以使用 sprintf 内置函数:

awk '{  = sprintf("%4d",  + n); print }  == "BAR:" { ++n; print "BAZ:", sprintf("%4d",  + n) }' filename

这将导致以下输出:

FOO:    1
BAR:    2
BAZ:    3
QUX:    4
...
ZYX:  100
XYZ:  101