2011-03-17 126 views
3

我想在我的m4文本中包含一個相對於我的沙盒基礎目錄的文件,而不使用-I開關。在m4中,如何包含名稱中包含環境變量的文件?

到目前爲止,我已經找到了如何使用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 

如何一個文件的路徑中是否包含環境變量?

回答

2

我認爲你需要使用esyscmd而不是syscmdesyscmd讀取命令行輸出。

+0

你確實是這個人。這工作。謝謝!有趣的是,除了'include'宏調用之外,我可以使用'MODEL_ROOT'。無論如何,謝謝! – 2011-03-17 23:48:55

1

正如其他答案所述,您必須使用GNU擴展esyscmd才能檢索命令的輸出。 syscmd宏只是直接打印到標準輸出,忽略所有宏和divert s。

這就是爲什麼它看起來像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') 

引號會阻止宏的擴展,所以它們不能將它放在此處(您希望將其展開的位置)。引用字符串的其餘部分是「恰當的」,因爲這不是你想要被宏擴展的東西。


順便說一句,一個更強大的方式來獲得從shell環境變量會是這樣的:

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

這將避免因宏名,百分號,反斜槓,水珠問題字符或環境變量值中的空格。這和你的解決方案之間的唯一區別是在變量周圍增加了\`\`%s\'\'和引號。

警告:esyscmd將始終將其輸出擴展爲宏,因此難以保持其真正的消毒效果。即使我使用上面的引號符號,如果這些引號符號存在於環境變量中,它仍然會跳動。