Поведение различных версий AWK при использовании шаблона регулярных выражений

Фон:

Недавно я попытался собрать libopencm3-examples на Ubuntu 14.04 и столкнулся с ошибкой сборки (в то время как для 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, например, но не ROM=256K (да?). Во всяком случае, как я уже упоминал /[[:upper:]]*=/ работает для Ubuntu 16.04 (GNU Awk 4.1.3) (почему?), а для 14.04 мне нужно было изменить /[[:upper:]]*=/ -> /[:upper:]*=/ заставить его работать (это ошибка или что?). Я что-то пропустил?

1 ответ

Решение

Нет, символ квадратной скобки является особенным в регулярном выражении. Если вы хотите соответствовать буквально, используйте \[, Выражение [:upper:] внутри квадратных скобок относится к классу символов, состоящему из символов верхнего регистра. Я предполагаю, что вы хотите

/[][:upper:][]+=/

сформировать выражение в скобках, состоящее из литеральной закрывающей квадратной скобки, заглавных символов и буквальной открывающей квадратной скобки. Обратите также внимание на переключение на + вместо * чтобы предотвратить совпадение на одиночном знаке равенства (* означает ноль или более, поэтому при нулевом повторении он будет совпадать с любым знаком равенства).

Возможно, ваш Awk вообще не поддерживает классы символов POSIX. Затем вы можете заменить [:upper:] с A-Z хотя тогда он не будет соответствовать чувствительности локали.

Другие вопросы по тегам