在 m4 中,如何包含名称中包含环境变量的文件?

发布于 2024-10-24 08:47:51 字数 1095 浏览 2 评论 0原文

我想在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

生活了然无味 2024-10-31 08:47:51

我认为您需要使用 esyscmd 而不是 syscmdesyscmd 读取命令行输出。

I think you need to use esyscmd instead of syscmd. esyscmd reads command line output.

空城仅有旧梦在 2024-10-31 08:47:51

正如另一个答案提到的,您必须使用 GNU 扩展 esyscmd 才能检索命令的输出。 syscmd 宏只是直接打印到 stdout,忽略所有宏和 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 宏的扩展,因此不得将其括在此处(您希望其扩展的位置)。引用字符串的其余部分是“正确的”,因为它不是您希望通过宏扩展的内容。


顺便说一句,从 shell 获取环境变量的更可靠的方法如下:

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

这将避免由环境变量值中的宏名称、百分号、反斜杠、全局字符或空格引起的问题。此解决方案与您的解决方案之间的唯一区别是在变量周围添加了 \`\`%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. The syscmd macro just prints directly to stdout, ignoring all macros and diverts.

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:

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

This should have the quotes moved:

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

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:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文