Как в m4 включить файл, в имени которого есть переменная окружения?

Я хочу включить файл, основанный на моем базовом каталоге песочницы, внутри моего текста m4 без использования переключателя -I.

До сих пор я понял, как получить переменные среды с помощью системного вызова:

define(MODEL_ROOT,`syscmd(`printf $MODEL_ROOT')')dnl

Затем я хочу включить файл на основе этой переменной среды:

include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)

Итого имею:

define(MODEL_ROOT,`syscmd(`printf $MODEL_ROOT')')

MODEL_ROOT

MODEL_ROOT/sw/lib/m4_macros/foreach2.m4

include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)

Что печатает:

/home/ross/sandbox

/home/ross/sandbox/sw/lib/m4_macros/foreach2.m4

/home/ross/sandboxforeach_example.m4:7: m4: Cannot open /sw/lib/m4_macros/foreach2.m4: No such file or directory

Я знаю, что нормальный синтаксис для include:

include(`file.m4')

Но если я цитирую MODEL_ROOT/sw/lib/m4_macros/foreach2.m4, то m4 вроде:

[...]
include(`MODEL_ROOT/sw/lib/m4_macros/foreach2.m4')

м4 жалуется:

[...]
foreach_example.m4:7: m4: Cannot open MODEL_ROOT/sw/lib/m4_macros/foreach2.m4: No such file or directory

Как включить файл с переменной окружения в его путь?


m4
person Ross Rogers    schedule 17.03.2011    source источник


Ответы (2)


Я думаю, вам нужно использовать esyscmd вместо syscmd. esyscmd читает вывод командной строки.

person dimba    schedule 17.03.2011
comment
Ты действительно мужчина. Это сработало. Спасибо! Что любопытно, так это то, что я действительно мог использовать MODEL_ROOT, за исключением вызова макроса include. В любом случае, спасибо! - person Ross Rogers; 18.03.2011

Как упоминается в другом ответе, вы должны использовать расширение GNU esyscmd, чтобы иметь возможность получить вывод команды. Макрос syscmd просто выводит прямо на стандартный вывод, игнорируя все макросы и divert.

Вот почему казалось, что MODEL_ROOT работает везде: так и было, но только в очень простых ситуациях, когда m4 не нужно было обрабатывать свой вывод.

Однако по поводу цитирования:

  • include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)
  • include(`MODEL_ROOT/sw/lib/m4_macros/foreach2.m4')

Это должно привести к перемещению кавычек:

include(MODEL_ROOT`/sw/lib/m4_macros/foreach2.m4')

Кавычки предотвращают расширение макроса MODEL_ROOT, поэтому они не должны заключать его здесь (там, где вы хотите, чтобы он был развернут). «Правильно» заключать в кавычки остальную часть строки, потому что это не то, что вы захотите расширить с помощью макросов.


Кроме того, более надежный способ получить переменную среды из оболочки будет выглядеть примерно так:

define(`HOME', esyscmd(`printf \`\`%s\'\' "$HOME"'))

Это позволит избежать проблем, вызванных именами макросов, знаками процента, обратной косой чертой, символами подстановки или пробелами в значении переменной среды. Единственное различие между этим и вашим решением заключается в добавлении \`\`%s\'\' и кавычек вокруг переменной.

Предостережение: вывод esyscmd всегда будет расширяться как макрос, поэтому может быть сложно сохранить его по-настоящему чистым. Несмотря на то, что я использую символы кавычек выше, он все равно сработает, если эти символы кавычек существуют в переменной среды.

person Score_Under    schedule 01.08.2016