make和shell入門
make基礎
1. make的顯式規則
在Linux作業系統下程式設計時,通常利用make命令來自動完成編譯工作。Make命令根據一個稱為makefile的檔案來完成並自動維護編譯工作。Makefile檔案需要按照某種語法進行編寫,其中說明了如何編譯各個原始檔並連結生成可執行檔案,並定義了原始檔之間的相互依賴關係。當修改了其中某個原始檔時,如果其他原始檔依賴於該檔案,則也要重新編譯所有依賴該檔案的原始檔。
Makefile檔案中包含一些規則來告訴make處理哪些檔案以及如何處理這些檔案。規則主要是描述哪些檔案(target目標檔案)是從哪些別的檔案(dependency依賴檔案)中產生的,以及用什麼命令(command)來執行這個過程。Makefile規則的一般形式如下:
target:dependencydependency
(tab) <command>
目標檔案(target)通常是可執行檔案或中間檔案,但也可以是要執行的動作,如“clean”。
依賴檔案(dependency)列表通常是編譯目標檔案所依賴的其他檔案。
命令(command)是建立target檔案所需要執行的步驟,比如編譯命令,每個命令佔一行,起始字元必須為TAB字元。
test: prog.ocode.o
gcc –o test prog.o code.o
prog.o: prog.c prog.h code.h
gcc –c prog.c –o prog.o
code.o: code.c code.h
gcc –c code.c –o code.o
clean:
rm –f *.o
左圖的makefile示例中共定義了四個目標:test、prog.o、code.o和clean。目標檔案與依賴檔案用":"分隔,多個依賴檔案以空格隔開,然後另起一行以tab開頭給出實現目標的命令。當命令過長時,使用"\"作為續行符。
例中已完成的程式原始碼為prog.c,prog.h,code.c,code.h,首先要使用make test或make(預設編譯makefile檔案中第一個目標)編譯程式。由於test依賴的prog.o和code.o檔案不存在,所以要先執行gcc –c prog.c –o prog.o
2. make變數的用法
在一行的開始給初變數名字,後面跟一個":="及要設定的值,即可定義變數:
VARNAME:=string
使用時把變數用括號{}括起來,並在前面加上$:
${VARNAME}
使用方法如下:
OBJS:=prog.o code.o
CC:=gcc
test: ${OBJS}
${CC} –o test ${OBJS}
prog.o: prog.c prog.h code.h
${CC} –c prog.c –o prog.o
code.o: code.c code.h
${CC} –c code.c –o code.o
clean:
rm–f *.o
Makefile檔案中還可以使用環境變數,以及預定義變數,如$@(目標名)、$^(所有的依賴檔案)、$<(第一個依賴檔案),
例如:
demo.o: demo.c demo.h
可以寫成:
gcc-c $< -o $@
3. make的隱式規則
make進行編譯時遵循一些稱作隱含規則的內建規則,這些規則在makefile中並沒有被完整地給出,但make知道沒有被給出的部分是什麼。(我理解為隱式規則可以不用給出)
典型的隱含規則給出了由.c檔案如何生成.o檔案,被隱含的規則是:
%.o: %.c
${CC} ${CFLAGS} $< -o $@
依據上面的隱含規則,前面的變數介紹中的示例程式碼可以省略為如下內容:
OBJS:=prog.o code.o
CC:=gcc
CFLAGS:=-c
test:${OBJS}
${CC} –o $@ $^
prog.o: prog.c prog.h code.h
code.o:code.c code.h
clean:
rm –f *.o
shell基礎
Shell也有多種不同的版本:
sh:GNU Bourne Shell
bash:GNU Bourne Again Shell(PC預設)
Korn Shell:大部分與BourneShell相容。
C Shell:是SUN公司Shell的BSD版本。
ZShell:集成了bash、ksh的重要特性。
通常在shell程式開始宣告型別,如 #!/bin/sh和 #!/bin/bash
1. shell的四個變數
1.1 使用者變數
shell允許把值存在變數中,shell變數名以字母或下劃線字元開始,由字母、數字或下劃線組成。要把值存入變數,只要寫出變數名,或緊跟一個=,再加變數值即可。
例如:variable=value
count=1
在程式中使用變數的值時,要在變數名前面加上一個符號“$”。
例如:echo $variable(echo的意思是列印後面的變數)
1.2 環境變數
環境變數是一種特殊的變數,可以由其他程式傳遞給指令碼,在指令碼中被呼叫的任何程式都將繼承環境變數。可以像定義一個變數一樣來設定環境變數,在標記它為環境變數時需要使用“export”命令:
export MYENV=1
echo $MYENV
使用set命令可以獲取當前上下文中全部的環境變數,使用env命令可以檢視系統中全部環境變數
1.3 位置變數
由出現命令列上的位置確定的引數稱做位置引數。總共有十個位置引數,其對應的名稱依次是$0,$1,$2,...$9,其中$0表示命令名或Shell指令碼名,不可或缺,其它位置引數可有可無。
編輯ison指令碼檔案內容如下:
who | grep $1
執行:chmod + x ison
./ison bc
shell將用bc取代$1,命令列變為
who | grep $bc
1.4 預定義變數
$#變數用於存放命令列中所鍵入的引數個數
$*變數可以引用傳遞給程式的所有引數
其中shift命令的作用是把位置引數左移,原來$1中的值丟失,引數變數的個數自動減1
$@變數和$*變數功能基本相同
$?變數: 每當程式執行完成後都會給系統返回一個退出狀態。該狀態是個數值,通常指示該命令執行是否成功。退出狀態為0表示執行成功,非零表示執行失敗。shell自動將最後所執行命令的退出狀態設定到shell變數$?中,可以用echo命令在終端上顯示它的值。
2. shell特殊字元與表示式
2.1 三種萬用字元
- *星號,它匹配任意字元的0次或多次出現。但注意,檔名前面的圓點(.)和路徑名中的斜線(/)必須顯式匹配。
- ?問號,匹配任意一個字元
- []一對方括號,其中有一個字元組。其作用是匹配該字元組所限定的任意一個字元。
注意*和?在方括號內,就不是萬用字元了。!歎號,若它緊跟在一對方括號的左方括號[之後,則表示不在一對方括號中所列出的字元。
2.2 引號與反斜線
- 雙引號""括起來的字元,除$、倒引號和反斜線(\)仍保留其功能外,其餘字元通常作為普通字元對待。
- 單引號''括起來的字元都作為普通字元出現。
- 倒(反)引號``用於設定系統命令的輸出到變數,反引號中的內容作為一個系統命令並執行。
- 反斜線\為轉義字元,若想在字串中使用反斜線本身,則必須採用(\\)的形式。
2.3 表示式
- 邏輯表示式:
&& : 與
|| : 或
! : 非(需要有空格) - expr求值表示式
expr命令一般用於整數值,但也可用於字串。一般格式為:expr argument operator argument 其中operator為 + - * / %,但對*的使用要用轉義符\。
示例如下:
v1=3
v2=2
v3=`expr $v1 * $v2 `
echo $v3
結果輸出6
3. shell條件判斷
3.1 if表示式
下面是if表示式的一般結構
if command1
then
...
elif command2
then
...
else
...
fi
command1和command2需要執行並檢測其退出狀態,如果退出狀態為0(command為真),則執行其後的then語句,否則就跳到else或者elif或fi。
下面是if用法的示例:
其中:
int1 –gt int2表示int1 大於int2
int1 –lt int2表示int1 小於int2
3.2 case表示式
case用法結構如下:
case string in
string1 )
...;;
string2 )
...;;
* )
...;;
esac
字串string首先與string1和string2比較,如果匹配就執行它們下面的語句直到雙分號。如果都不匹配,則執行* )下面的語句。
下面是case用法的示例:
4. shell迴圈
4.1 for迴圈
for迴圈分為帶列表和不帶列表的。
帶列表將一組命令迴圈執行預先確定的次數,基本方法如下:
不帶列表的形式,shell會自動將命令列鍵入的所有引數依次組織成列表。
4.2 while迴圈
while迴圈示例如下:
break命令與continue命令與C中相應命令功能相同。
5. shell函式
和“真正的”程式語言一樣,shell也有函式,雖然在某些實現方面稍有些限制。
函式被呼叫或被觸發,只需要簡單地使用函式名即可。
函式示例如下: