使用正则表达式模式时 AWK 不同版本的行为
AWK different versions behavior when using regex pattern
背景:
最近我尝试在 Ubuntu 14.04 上构建 libopencm3-examples 并遇到构建错误(而对于 Ubuntu 16.04.1 LTS,它工作正常)。我开始挖掘以找出原因。正如我所发现的,libopencm3 使用特定的链接描述文件生成器:
见libopencm3-examples/libopencm3/ld/README
此工具的目的是将目标微控制器的特定定义传递给链接描述文件模板。所以它在模板脚本下使用预处理器并传递目标特定参数,如下所示:
-D_FPU=hard-fpv5-sp-d16 -D_ROM_OFF=0x08000000 -D_RAM_OFF=0x20000000
使用 awk 脚本检索此参数。
./libopencm3/scripts/genlink.awk
用于生成 -D_XXX 密钥此脚本在设备数据库下运行 ./libopencm3/ld/devices.data
像这样:
awk -v PAT="$(DEVICE)" -v MODE="DEFS" -f $(OPENCM3_DIR)/scripts/genlink.awk $(OPENCM3_DIR)/ld/devices.data
问题:
awk 脚本部分,从数据库中提取定义信息如下所示:
...
for (i = 3; i <= NF; i = i + 1) {
...
else if ($i ~ /[[:upper:]]*=/) {
if ("DEFS" == MODE)
printf "-D_%s ",$i;
}
}
数据库中的行,由脚本处理:
stm32f3[01]3?c* stm32f3ccm ROM=256K RAM=40K CCM=8K
让我感到困惑的是,建议的模式 (/[[:upper:]]*=/
) 应该匹配 [ROM]=256K f.e,但不是 ROM=256K(是吗?)。无论如何,正如我已经提到的,/[[:upper:]]*=/
适用于 ubuntu 16.04(GNU Awk 4.1.3)(为什么?),而对于 14.04,我需要更改 /[[:upper:]]*=/
-> /[:upper:]*=/
强制它工作(这是一个错误还是什么?)。我错过了什么吗?
不,方括号字符在正则表达式中是特殊的。如果要按字面匹配,使用\[
。方括号内的表达式[:upper:]
指的是由大写字符组成的字符class。我猜你想要
/[][:upper:][]+=/
组成括号表达式,由文字右方括号、大写字符和文字左方括号组成。还要注意切换到 +
而不是 *
以防止在单独的等号上匹配(*
表示零个或多个,因此对于零重复,它将匹配任何等号)。
可能您的 Awk 根本不支持 POSIX 字符 classes。然后,您可以将 [:upper:]
替换为 A-Z
,尽管它不会敏感地匹配语言环境。
背景:
最近我尝试在 Ubuntu 14.04 上构建 libopencm3-examples 并遇到构建错误(而对于 Ubuntu 16.04.1 LTS,它工作正常)。我开始挖掘以找出原因。正如我所发现的,libopencm3 使用特定的链接描述文件生成器:
见libopencm3-examples/libopencm3/ld/README
此工具的目的是将目标微控制器的特定定义传递给链接描述文件模板。所以它在模板脚本下使用预处理器并传递目标特定参数,如下所示:
-D_FPU=hard-fpv5-sp-d16 -D_ROM_OFF=0x08000000 -D_RAM_OFF=0x20000000
使用 awk 脚本检索此参数。
./libopencm3/scripts/genlink.awk
用于生成 -D_XXX 密钥此脚本在设备数据库下运行 ./libopencm3/ld/devices.data
像这样:
awk -v PAT="$(DEVICE)" -v MODE="DEFS" -f $(OPENCM3_DIR)/scripts/genlink.awk $(OPENCM3_DIR)/ld/devices.data
问题:
awk 脚本部分,从数据库中提取定义信息如下所示:
...
for (i = 3; i <= NF; i = i + 1) {
...
else if ($i ~ /[[:upper:]]*=/) {
if ("DEFS" == MODE)
printf "-D_%s ",$i;
}
}
数据库中的行,由脚本处理:
stm32f3[01]3?c* stm32f3ccm ROM=256K RAM=40K CCM=8K
让我感到困惑的是,建议的模式 (/[[:upper:]]*=/
) 应该匹配 [ROM]=256K f.e,但不是 ROM=256K(是吗?)。无论如何,正如我已经提到的,/[[:upper:]]*=/
适用于 ubuntu 16.04(GNU Awk 4.1.3)(为什么?),而对于 14.04,我需要更改 /[[:upper:]]*=/
-> /[:upper:]*=/
强制它工作(这是一个错误还是什么?)。我错过了什么吗?
不,方括号字符在正则表达式中是特殊的。如果要按字面匹配,使用\[
。方括号内的表达式[:upper:]
指的是由大写字符组成的字符class。我猜你想要
/[][:upper:][]+=/
组成括号表达式,由文字右方括号、大写字符和文字左方括号组成。还要注意切换到 +
而不是 *
以防止在单独的等号上匹配(*
表示零个或多个,因此对于零重复,它将匹配任何等号)。
可能您的 Awk 根本不支持 POSIX 字符 classes。然后,您可以将 [:upper:]
替换为 A-Z
,尽管它不会敏感地匹配语言环境。