在 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(`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
如何在其路径中包含一个带有环境变量的文件?
I want to include a file based relative to my sandbox base directory inside of my m4 text without using the -I
switch.
So far, I have figured out how to grab the environment variables using a sys call:
define(MODEL_ROOT,`syscmd(`printf $MODEL_ROOT')')dnl
Next, I want to include a file based off that environment variable:
include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)
In total, I have:
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)
Which prints:
/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
I know that the normal syntax for includes is
include(`file.m4')
But if I quote MODEL_ROOT/sw/lib/m4_macros/foreach2.m4
, then m4 like:
[...]
include(`MODEL_ROOT/sw/lib/m4_macros/foreach2.m4')
m4 complains:
[...]
foreach_example.m4:7: m4: Cannot open MODEL_ROOT/sw/lib/m4_macros/foreach2.m4: No such file or directory
How does one include a file with an environment variable in its path?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您需要使用
esyscmd
而不是syscmd
。esyscmd
读取命令行输出。I think you need to use
esyscmd
instead ofsyscmd
.esyscmd
reads command line output.正如另一个答案提到的,您必须使用 GNU 扩展 esyscmd 才能检索命令的输出。
syscmd
宏只是直接打印到 stdout,忽略所有宏和divert
。这就是为什么它看起来像
MODEL_ROOT
在其他地方都可以工作:确实如此,但仅在 m4 不需要处理其输出的非常简单的情况下。然而,关于引用:
这应该移动引号:
引号会阻止
MODEL_ROOT
宏的扩展,因此不得将其括在此处(您希望其扩展的位置)。引用字符串的其余部分是“正确的”,因为它不是您希望通过宏扩展的内容。顺便说一句,从 shell 获取环境变量的更可靠的方法如下:
这将避免由环境变量值中的宏名称、百分号、反斜杠、全局字符或空格引起的问题。此解决方案与您的解决方案之间的唯一区别是在变量周围添加了
\`\`%s\'\'
和引号。需要注意的是:
esyscmd
始终会将其输出扩展为宏,因此很难对其进行真正的清理。即使我在上面使用引号符号,如果环境变量中存在这些引号符号,它仍然会出错。As the other answer mentions, you have to use the GNU extension
esyscmd
to be able to retrieve the output of the command. Thesyscmd
macro just prints directly to stdout, ignoring all macros anddivert
s.That is why it looked like
MODEL_ROOT
was working everywhere else: it was, but only in very simple situations where m4 didn't need to deal with its output.However, regarding quoting:
This should have the quotes moved:
The quotes prevent expansion of the
MODEL_ROOT
macro, so they must not enclose it here (where you want it to be expanded). It is "proper" to quote the rest of the string, because it's not something you will want to be expanded by macros.As an aside, a more robust way to get an environment variable from the shell would be something like:
That will avoid problems caused by macro names, percentage signs, backslashes, glob characters, or whitespace in the environment variable's value. The only differences between this and your solution are the addition of
\`\`%s\'\'
and quotes around the variable.A caveat:
esyscmd
will always have its output expanded as a macro, so it can be difficult to keep it truly sanitized. Even though I'm using quote symbols above, it will still trip up if those quote symbols exist in the environment variable.