Makefile中echo -e 以及 輸出$()和%.o 這兩個字符串的問題

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/haifeng_gu/article/details/73332242

背景

有次我在寫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 這兩個字符串。求高人指點,謝謝!!



歡迎大家在評論中指正!

Reference

makefile中使用echo -e引發的思考(涉及dash和bash)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章