2013-02-07 87 views
2

我有一個變量,其中包含以字符串_NEWLINE_分隔的文件列表。我需要將該變量輸出到一個文件中,以便每個文件位於不同的行中。訣竅是它需要在FreeBSD和Solaris上工作。如何在GNU makefile中將文件分割成單獨的行

這是我現在想:

echo "lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf" | sed 's|_NEWLINE_|\'$'\n|g' 

這個工程在FreeBSD和Solaris上殼。但在GNUmakefile運行在Solaris上我得到這個(在每一行結束通知$):

lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf$ 
lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src$ 
lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf$ 

如果我從SED刪除\'$'然後它工作在Solaris上,但沒有在FreeBSD。也許有一種方法告訴哪個版本的使用取決於哪個系統的makefile被執行?

編輯: 感謝我創建了一個提供所需的結果,似乎是工作在兩個FreeBSD和Solaris上示範的makefile bobbogo提出解決方案:

one-line := lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/\ 
priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/comm\ 
unity.conf: lib/alarms/priv/snmp_conf/community.conf 

many-lines := { echo '$(subst _NEWLINE_,' && echo ',${one-line})'; } 

.PHONY: all 
all: 
    $(shell $(many-lines) > test.txt) 
+0

在閱讀接受的答案後,在我看來,上面最初的'sed'方法是一種更簡單的方法(參見@ Beta的答案)。儘管使用perl。 perl是其中最具可移植性的語言之一,它總是勝過grep/sed/awk et。人。 'echo'$ {one-line}'| perl -lpe的/ _NEWLINE _/\ n/g''也許。 (或者perl -lpe BEGIN {$$/=「_NEWLINE_」}「-timtowtdi,就像Perl的人說的那樣)。 – bobbogo

回答

1

如果這是GNU做,然後做這一切在化妝。

one-line := lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf 

define \n 


endef 

many-lines := $(subst _NEWLINE_,${\n},${one-line}) 

現在${many-lines}正是你想要的。令人煩惱的是,在殼線上使用相當困難。如果你這樣做:

tgt: 
    echo '${many-lines}' 

作將調用單獨外殼爲每個線。第一次shell調用將得到一個未配對的',並退出時出現錯誤。

.ONESHELL: 
tgt: 
    echo '${many-lines}' 

將以侵入式的方式工作。正確的解決方法是確保${many-lines}的每一行都有有效的sh語法。一些類似於:

echolines = $(subst ${\n},'${\n}echo ',echo '${many-lines}') 
.PHONY: aa 
aa: 
    $(call echolines,${many-lines}) 

呃。

+0

謝謝,這是一個好的開始。我正在考慮類似的事情,但沒有耐心弄清楚在哪裏擺放回聲。你能夠在文件中添加每一行的回顯,因爲這是最終的目標嗎?我認爲在你的方法中,每行應該有這樣的格式:「echo'target:file'>> test.txt」但是我不知道在哪裏添加「>> test.txt」部分。對我來說,最後一行看起來會有問題,因爲它不以「\ n」結尾,不能輕易替換。我的意思是,在最後添加_NEWLINE_應該仍然可以,但是會變得更加混亂。 – Amiramix

+0

其實,我認爲我得到'$ echolines'錯誤,因爲echo總是添加一個換行符(除了''echo's中的'-c'外)。睡過之後,更好的方法是將'str1 \ nstr2 \ nstr3 \ n'變成'{echo'str1'&& echo'str2'&& echo'str3'}''。這是一個單獨的shell調用,並且對於單一的間接尋址('$(call echolines2,$ {many-lines})> $ @')會很滿意。 – bobbogo

+0

我不確定我可能做錯了什麼,但仍然不起作用:'many-lines:= echo'$(subst _NEWLINE_,'&& echo',$ {one-line})'''echolines = $ (subst $ {\ n},'$ {\ n} echo',$ {many-lines})''$(call echolines,$ {many-lines})> test.txt'在文件中打印一行,另外兩個到標準輸出。 – Amiramix

0

免責聲明:我有沒有使用Solaris或FreeBSD的經驗...無論如何。

在make中,您可以使用$(patsubst pattern,replacement,text)來替換一個模式。 試試這個...

FILENAMES := "lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf" 

.PHONY: all 

all: 
    @echo $(patsubst _NEWLINE_,${\n},$(FILENAMES)) 
+0

這不起作用,因爲_NEWLINE_不是與其他詞分開的空格。但謝謝你的嘗試。 – Amiramix

+0

順便說一句,使用subst而不是patsubst也不起作用(因爲\ n沒有被正確替換)。我想你沒有測試你的代碼? – Amiramix

1

嘗試過許多不同的解決方案,包括本答覆中提到定義\nAdd a newline in Makefile 'foreach' loop

真正的問題是實現跨平臺的echo命令的不一致,而事實上,由默認make使用sh調用shell命令,它本身非常不靈活。

我發現了一個更好的感謝這樣的回答方式:"echo -e" when called directly and when called via a shell-script

更好的方法是使用printf代替echo

構建字符串\n代替_NEWLINE_分離是進入單獨的部分輸出文件中的行:

some_string = lib/alarms-1.2/priv/snmp_conf/target_params.conf: lib/alarms/priv/snmp_conf/target_params.conf\nlib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf\n 

然後在makefile中打印它只是簡單的這個:

@printf "$(some_string)" >> $(some_file) 

適用於FreeBSD和Solaris。

+0

這在_some_string_包含'%'字符的情況下很脆弱。 – bobbogo

0

作爲替代,我想你的第一種方法將工作,如果你要加倍$「逃離」是:

sed 's|_NEWLINE_|\'$$'\n|g' 
+0

不,它沒有。在Solaris上它輸出conf $ nlib(用$ n替換_NEWLINE_)。 – Amiramix

相關問題