背景
有次我在寫makfile時,用echo -e要顯示帶顏色的文字,命令如下:
echo -e “Full Version is:\033[31m\033[1m v1.0 \033[0m”;
該命令在控制檯中單獨執行都顯示正常,效果如下:
Full Version is: v1.0
可以放在makefile中一運行, 結果把-e也顯示出來:
-e Full Version is: v1.0
原因
這是由於不同的shell(一個是bash,一個是dash)造成的兩種不同的結果,即在bash下正常,在dash下就多顯示了一個-e。
從Ubuntu 6.10開始,默認使用的shell是dash,而不是bash,原因是dash更快、更高效,使用dash可以加快啓動速度。
我們可以做如下實驗來驗證下,先啓用bash運行下指令,再啓用dash試試:
$ /bin/bash
$ echo -e "Full Version is:\033[31m\033[1m v1.0 \033[0m";
Full Version is: v1.0
$ exit
exit
$
$ /bin/dash
$ echo -e "Full Version is:\033[31m\033[1m v1.0 \033[0m";
-e Full Version is: v1.0
$ exit
$
makefile用的是哪個shell
makefile默認用的shell是/bin/sh。但/bin/sh緊緊是個鏈接文件,到底用的是什麼shell程序可以通過ls查看:
$ ls -l /bin/sh
0 lrwxrwxrwx 1 root root 4 6月 20 2012 /bin/sh -> dash
而系統默認的shell可以通過系統環境變量SHELL查看,當前shell可以通$0查看:
$ echo $SHELL
/bin/bash
$ echo $0
-bash
至此,之所以會出現前面所述的問題,就是這個原因了:在makefile中用的是/bin/dash,而在控制檯中用的是/bin/bash。
那makefile能不能顯式地指定由哪個shell程序來運行命令呢?答案是肯定的。makefile本身有個環境變量也叫SHELL(跟系統環境變量SHELL同名,但不一樣),我們可以在makefile中明確地給他賦值,以指明用哪個shell程序來解析命令。如SHELL=/bin/bash。
我在makefile最前面加上SHELL=/bin/bash,問題就解決了。
我試了下網上部分同學說的在Makefile開頭使用 #!/bin/bash 的方式,但似乎不起作用,echo $(SHELL) 依然是/bin/sh (即指向了默認的/bin/dash)。
現在我有另一個問題,就是怎麼在Makefile中通過echo打印出$()和%.o 這兩個字符串?
我們知道,$()和% 在shell中屬於特殊字符,打印時需要escape(轉義)。
- $(command) 相當於2個反引號
`command`
,也用作命令替換,即先執行括號中的命令,然後返回命令執行的結果。 - % 在參數替換(parameter substitution)中,可以作爲模式匹配。在算術運算中,這個是求模操作符。
在ubuntu終端命令行下直接執行下列命令輸出是OK的,如下:
jeremy@compute1:~/xx$ echo $SHELL
/bin/bash 這個輸出說明當前shell使用的是bash
jeremy@compute1:~/xx$ echo $0
-bash 同上
jeremy@compute1:~/xx$ echo -e "\$ \b()"
輸出爲$()
jeremy@compute1:~/xx$ echo -e "\$() + \%.o"
輸出爲$() + %.o
echo的選項:
-n 不要在最後自動換行
-e 若字符串中出現以下字符,則特別加以處理,而不會將它當成一般
文字輸出:
\a 發出警告聲;
\b 刪除前一個字符;(如單詞間的空格)
\c 最後不加上換行符號;
\f 換行但光標仍舊停留在原來的位置;
\n 換行且光標移至行首;
\r 光標移至行首,但不換行;
\t 插入tab;
\v 與\f相同;
\\ 插入\字符;
\nnn 插入nnn(八進制)所代表的ASCII字符;
–help 顯示幫助
–version 顯示版本信息
但是在Makefile中,使用同樣的echo指令,同樣是bash,輸出結果卻不對。。。
Makefile的內容如下(其中第一行SHELL=/bin/bash先註釋掉):
#SHELL=/bin/bash
.PHONY: clean all
all:
@echo $(SHELL)
@echo -e "\$ \b()"
clean:
@echo -e "\$() + \%.o"
執行結果如下:
jeremy@compute1:~/xx$ make all
/bin/sh
-e()
jeremy@compute1:~/xx$ make clean
-e \ + \%.o
現在將Makefile中第一行SHELL=/bin/bash啓用:
SHELL=/bin/bash
.PHONY: clean all
all:
@echo $(SHELL)
@echo -e "\$ \b()"
clean:
@echo -e "\$() + \%.o"
執行結果如下:
jeremy@compute1:~/xx$ make all
/bin/bash 啓用SHELL=/bin/bash後,
() 前面的-e確實沒有了,但爲何不是輸出$()呢??
jeremy@compute1:~/xx$ make clean
\ + \%.o
結論:
- 在Makefile中第一行設定SHELL=/bin/bash後,echo輸出就不會顯示-e選項了
- echo格式化輸出(-e 參數)需要bash支持
- 還是沒解決Makefile中echo打印出$()和%.o 這兩個字符串。求高人指點,謝謝!!
歡迎大家在評論中指正!