我在下面有一些代码,并且只想匹配定义_AA(见下面的代码)时定义的版本字符串。
#ifdef _AA
#define VER 1.0.0.1
#define VER2 1.0.0.1
#else
#define VER 1.0.0.1
#define VER2 1.0.0.1
#endif
我使用这种模式匹配每个版本字符串:
[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+
但我不知道如何只匹配代码 _AA part 中的版本字符串。
c.f。我正在使用gnu sed,最终目标是增加匹配版本字符串的次要版本号。
答案 0 :(得分:3)
要仅在_AA
区域内匹配,请使用地址说明符:
$ sed -n -r '/_AA/,/#else/ {/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/p}' file
#define VER 1.0.0.1
#define VER2 1.0.0.1
工作原理:
-n
这告诉sed不要打印任何行,除非我们明确要求它。
-r
这会选择扩展的正则表达式格式。
/_AA/,/#else/
这是地址范围选择器。当遇到_AA
的行时,它会开始匹配。它继续并包括匹配#else
的第一行。
/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/p
在与范围选择器匹配的行中,选择并打印与版本正则表达式匹配的行。
[.]
是匹配句点的好方法。虽然.
通常是通配符,但在方括号中它会失去特殊含义。
您提到最终目标是增加次要版本号。我会选择awk
来执行此任务,因为sed
不擅长数学:
$ awk -F. -v OFS=. '/_AA/,/#else/ {if (/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/) {$NF=$NF+1}}; {print}' file
#ifdef _AA
#define VER 1.0.0.2
#define VER2 1.0.0.2
#else
#define VER 1.0.0.1
#define VER2 1.0.0.1
#endif
工作原理:
-F. -v OFS=.
这告诉awk
为输入和输出字段分隔符使用句点。使用.
作为字段分隔符,可以轻松地增加次要版本号。
/_AA/,/#else/ {if (/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/) {$NF=$NF+1}};
这从/_AA/,/#else/
开始,这是一个地址范围选择器,就像sed
版本一样。
在该地址范围内的行中,if
语句进一步选择具有版本号的行。对于这些行,最后一个字段$NF
是次要版本号,并且加1。
{print}
最后,所有行都会打印出来。
使用sed
,可以使用-i
选项(或OSX上的-i""
)对文件进行编辑。
新版本的GNU awk
(4.1.0或更高版本)也有一个就地编辑选项,类似于“sed -i”。
对于awk
的旧版本,可以按如下方式模拟就地编辑:
awk -F. -v OFS=. '/_AA/,/#else/ {if (/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/) {$NF=$NF+1}}; {print}' file > tmp && mv tmp file
sed -i
而较新的awk
并未真正进行就地编辑。它们还会写入临时文件,然后使用它来覆盖源文件。因此,就地功能仅仅是打字快捷方式。
答案 1 :(得分:1)
如果您愿意接受其他建议;使用Perl单行程序在这些模式之间打印版本字符串。
perl -ne 'if (/_AA/../#else/) { print unless /_AA/ or /#else/ }' file
#define VER 1.0.0.1
#define VER2 1.0.0.1
如果您想删除前导空格:
perl -ne 'if (/_AA/../#else/) { s/^\s+// and print unless /_AA/ or /#else/ }' file
#define VER 1.0.0.1
#define VER2 1.0.0.1
答案 2 :(得分:0)