В m4, как да включите файл, който има променлива на средата в името си?

Искам да включа файл, базиран на моята базова директория на пясъчника, в моя m4 текст, без да използвам превключвателя -I.

Досега разбрах как да взема променливите на средата с помощта на sys извикване:

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(`file.m4')

Но ако цитирам MODEL_ROOT/sw/lib/m4_macros/foreach2.m4, тогава m4 като:

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

m4 се оплаква:

[...]
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 просто се отпечатва директно в stdout, като игнорира всички макроси и diverts.

Ето защо изглеждаше, че 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