增加源文件中的所有 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
假设我有很多 (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