亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 『轉(zhuǎn)貼』Bash 實例 [打印本頁]

作者: dinlin2000    時間: 2005-09-08 11:48
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
Bash 實例,第 2 部分   
  


   
內(nèi)容:

接收自變量

Bash 編程結(jié)構(gòu)

方便的條件語句

字符串比較說明

循環(huán)結(jié)構(gòu):"for"

Shell 算術(shù)

更多的循環(huán)結(jié)構(gòu):"while" 和 "until"

Case 語句

函數(shù)與名稱空間

名稱空間

結(jié)束語

參考資料  

關(guān)于作者

對本文的評價



訂閱:

developerWorks 時事通訊






更多的 bash 基本編程

Daniel Robbins
總裁兼 CEO, Gentoo Technologies, Inc.
2000 年 4 月

在前一篇 bash 的介紹性文章中,Daniel Robbins 為您講解了腳本語言的一些基本元素和使用 bash 的原因。在本文(即第二部分)中,Daniel 繼續(xù)前一篇的內(nèi)容,并講解條件 (if-then) 語句、循環(huán)和更多的 bash 基本結(jié)構(gòu)。
我們先看一下處理命令行自變量的簡單技巧,然后再看看 bash 基本編程結(jié)構(gòu)。

接收自變量
在 介紹性文章 中的樣本程序中,我們使用環(huán)境變量 "$1" 來引用第一個命令行自變量。類似地,可以使用 "$2"、"$3" 等來引用傳遞給腳本的第二和第三個自變量。這里有一個例子:



#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#



除以下兩個細節(jié)之外,此例無需說明。第一,"$0" 將擴展成從命令行調(diào)用的腳本名稱,"$#" 將擴展成傳遞給腳本的自變量數(shù)目。試驗以上腳本,通過傳遞不同類型的命令行自變量來了解其工作原理。

有時需要一次引用 所有 命令行自變量。針對這種用途,bash 實現(xiàn)了變量 "$@",它擴展成所有用空格分開的命令行參數(shù)。在本文稍后的 "for" 循環(huán)部分中,您將看到使用該變量的例子。

Bash 編程結(jié)構(gòu)
如果您曾用過如 C、Pascal、Python 或 Perl 那樣的過程語言編程,則一定熟悉 "if" 語句和 "for" 循環(huán)那樣的標(biāo)準(zhǔn)編程結(jié)構(gòu)。對于這些標(biāo)準(zhǔn)結(jié)構(gòu)的大多數(shù),Bash 有自己的版本。在下幾節(jié)中,將介紹幾種 bash 結(jié)構(gòu),并演示這些結(jié)構(gòu)和您已經(jīng)熟悉的其它編程語言中結(jié)構(gòu)的差異。如果以前編程不多,也不必擔(dān)心。我提供了足夠的信息和示例,使您可以跟上本文的進度。

方便的條件語句
如果您曾用 C 編寫過與文件相關(guān)的代碼,則應(yīng)該知道:要比較特定文件是否比另一個文件新需要大量工作。那是因為 C 沒有任何內(nèi)置語法來進行這種比較,必須使用兩個 stat() 調(diào)用和兩個 stat 結(jié)構(gòu)來進行手工比較。相反,bash 內(nèi)置了標(biāo)準(zhǔn)文件比較運算符,因此,確定“/tmp/myfile 是否可讀”與查看“$myvar 是否大于 4”一樣容易。

下表列出最常用的 bash 比較運算符。同時還有如何正確使用每一選項的示例。示例要跟在 "if" 之后。例如:



if [ -z "$myvar" ]
then
    echo "myvar is not defined"
fi




運算符  描述  示例  
文件比較運算符  
-e filename  如果 filename存在,則為真  [ -e /var/log/syslog ]
-d filename  如果 filename為目錄,則為真  [ -d /tmp/mydir ]
-f filename  如果 filename為常規(guī)文件,則為真  [ -f /usr/bin/grep ]
-L filename  如果 filename為符號鏈接,則為真  [ -L /usr/bin/grep ]
-r filename  如果 filename可讀,則為真  [ -r /var/log/syslog ]
-w filename  如果 filename可寫,則為真  [ -w /var/mytmp.txt ]
-x filename  如果 filename可執(zhí)行,則為真  [ -L /usr/bin/grep ]
filename1-nt filename2  如果 filename1比 filename2新,則為真  [ /tmp/install/etc/services -nt /etc/services ]
filename1-ot filename2  如果 filename1比 filename2舊,則為真  [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比較運算符 (請注意引號的使用,這是防止空格擾亂代碼的好方法)  
-z string  如果 string長度為零,則為真  [ -z "$myvar" ]
-n string  如果 string長度非零,則為真  [ -n "$myvar" ]
string1= string2  如果 string1與 string2相同,則為真  [ "$myvar" = "one two three" ]
string1!= string2  如果 string1與 string2不同,則為真  [ "$myvar" != "one two three" ]
算術(shù)比較運算符  
num1-eq num2  等于 [ 3 -eq $mynum ]
num1-ne num2  不等于 [ 3 -ne $mynum ]
num1-lt num2  小于 [ 3 -lt $mynum ]
num1-le num2  小于或等于 [ 3 -le $mynum ]
num1-gt num2  大于 [ 3 -gt $mynum ]
num1-ge num2  大于或等于 [ 3 -ge $mynum ]

有時,有幾種不同方法來進行特定比較。例如,以下兩個代碼段的功能相同:



if [ "$myvar" -eq 3 ]
then
     echo "myvar equals 3"
fi


if [ "$myvar" = "3" ]
then
     echo "myvar equals 3"
fi



上面兩個比較執(zhí)行相同的功能,但是第一個使用算術(shù)比較運算符,而第二個使用字符串比較運算符。

字符串比較說明
大多數(shù)時候,雖然可以不使用括起字符串和字符串變量的雙引號,但這并不是好主意。為什么呢?因為如果環(huán)境變量中恰巧有一個空格或制表鍵,bash 將無法分辨,從而無法正常工作。這里有一個錯誤的比較示例:



if [ $myvar = "foo bar oni" ]
then
     echo "yes"
fi



在上例中,如果 myvar 等于 "foo",則代碼將按預(yù)想工作,不進行打印。但是,如果 myvar 等于 "foo bar oni",則代碼將因以下錯誤失。



[: too many arguments



在這種情況下,"$myvar"(等于 "foo bar oni")中的空格迷惑了 bash。bash 擴展 "$myvar" 之后,代碼如下:



[ foo bar oni = "foo bar oni" ]



因為環(huán)境變量沒放在雙引號中,所以 bash 認為方括號中的自變量過多?梢杂秒p引號將字符串自變量括起來消除該問題。請記住,如果養(yǎng)成將所有字符串自變量用雙引號括起的習(xí)慣,將除去很多類似的編程錯誤。"foo bar oni" 比較 應(yīng)該寫成:



if [ "$myvar" = "foo bar oni" ]
then
     echo "yes"
fi



更多引用細節(jié)
如果要擴展環(huán)境變量,則必須將它們用 雙引號、而不是單引號括起。單引號 禁用 變量(和歷史)擴展。


以上代碼將按預(yù)想工作,而不會有任何令人不快的意外出現(xiàn)。

循環(huán)結(jié)構(gòu):"for"
好了,已經(jīng)講了條件語句,下面該探索 bash 循環(huán)結(jié)構(gòu)了。我們將從標(biāo)準(zhǔn)的 "for" 循環(huán)開始。這里有一個簡單的例子:




#!/usr/bin/env bash

for x in one two three four
do
     echo number $x
done


        輸出:

number one
number two
number three
number four

      


發(fā)生了什么?"for" 循環(huán)中的 "for x" 部分定義了一個名為 "$x" 的新環(huán)境變量(也稱為循環(huán)控制變量),它的值被依次設(shè)置為 "one"、"two"、"three" 和 "four"。每一次賦值之后,執(zhí)行一次循環(huán)體("do" 和 "done" 之間的代碼)。在循環(huán)體內(nèi),象其它環(huán)境變量一樣,使用標(biāo)準(zhǔn)的變量擴展語法來引用循環(huán)控制變量 "$x"。還要注意,"for" 循環(huán)總是接收 "in" 語句之后的某種類型的字列表。在本例中,指定了四個英語單詞,但是字列表也可以引用磁盤上的文件,甚至文件通配符。看看下面的例子,該例演示如何使用標(biāo)準(zhǔn) shell 通配符:



#!/usr/bin/env bash

for myfile in /etc/r*
do
     if [ -d "$myfile" ]
then
       echo "$myfile (dir)"
else
       echo "$myfile"
fi
done


        輸出:

/etc/rc.d (dir)
/etc/resolv.conf
/etc/resolv.conf~
/etc/rpc                  

      


以上代碼列出在 /etc 中每個以 "r" 開頭的文件。要做到這點,bash 在執(zhí)行循環(huán)之前首先取得通配符 /etc/r*,然后擴展它,用字符串 /etc/rc.d /etc/resolv.conf /etc/resolv.conf~ /etc/rpc 替換。一旦進入循環(huán),根據(jù) myfile 是否為目錄,"-d" 條件運算符用來執(zhí)行兩個不同操作。如果是目錄,則將 "(dir)" 附加到輸出行。

還可以在字列表中使用多個通配符、甚至是環(huán)境變量:




for x in /etc/r--? /var/lo* /home/drobbins/mystuff/* /tmp/${MYPATH}/*
do
     cp $x /mnt/mydir
done



Bash 將在所有正確位置上執(zhí)行通配符和環(huán)境變量擴展,并可能創(chuàng)建一個非常長的字列表。

雖然所有通配符擴展示例使用了 絕對路徑,但也可以使用相對路徑,如下所示:




for x in ../* mystuff/*
do
     echo $x is a silly file
done



在上例中,bash 相對于當(dāng)前工作目錄執(zhí)行通配符擴展,就象在命令行中使用相對路徑一樣。研究一下通配符擴展。您將注意到,如果在通配符中使用絕對路徑,bash 將通配符擴展成一個絕對路徑列表。否則,bash 將在后面的字列表中使用相對路徑。如果只引用當(dāng)前工作目錄中的文件(例如,如果輸入 "for x in *"),則產(chǎn)生的文件列表將沒有路徑信息的前綴。請記住,可以使用 "basename" 可執(zhí)行程序來除去前面的路徑信息,如下所示:




for x in /var/log/*
do
     echo `basename $x` is a file living in /var/log
done



當(dāng)然,在腳本的命令行自變量上執(zhí)行循環(huán)通常很方便。這里有一個如何使用本文開始提到的 "$@" 變量的例子:




#!/usr/bin/env bash

for thing in "$@"
do
     echo you typed ${thing}.
done


        輸出:

$ allargs hello there you silly
you typed hello.
you typed there.
you typed you.
you typed silly.

      


Shell 算術(shù)
在學(xué)習(xí)另一類型的循環(huán)結(jié)構(gòu)之前,最好先熟悉如何執(zhí)行 shell 算術(shù)。是的,確實如此:可以使用 shell 結(jié)構(gòu)來執(zhí)行簡單的整數(shù)運算。只需將特定的算術(shù)表達式用 "$((" 和 ")" 括起,bash 就可以計算表達式。這里有一些例子:



$ echo $(( 100 / 3 ))
33
$ myvar="56"
$ echo $(( $myvar + 12 ))
68
$ echo $(( $myvar - $myvar ))
0 $ myvar=$(( $myvar + 1 ))
$ echo $myvar
57



更多的循環(huán)結(jié)構(gòu):"while" 和 "until"
只要特定條件為真,"while" 語句就會執(zhí)行,其格式如下:



while [ condition ]
do
     statements
done



通常使用 "While" 語句來循環(huán)一定次數(shù),比如,下例將循環(huán) 10 次:



myvar=0
while [ $myvar -ne 10 ]
do
     echo $myvar
     myvar=$(( $myvar + 1 ))
done



可以看到,上例使用了算術(shù)表達式來使條件最終為假,并導(dǎo)致循環(huán)終止。

"Until" 語句提供了與 "while" 語句相反的功能:只要特定條件為 假 ,它們就重復(fù)。下面是一個與前面的 "while" 循環(huán)具有同等功能的 "until" 循環(huán):



myvar=0
until [ $myvar -eq 10 ]
do
     echo $myvar
     myvar=$(( $myvar + 1 ))
done



Case 語句
Case 語句是另一種便利的條件結(jié)構(gòu)。這里有一個示例片段:




case "${x##*.}" in
      gz)
            gzunpack ${SROOT}/${x}
            ;;
      bz2)
            bz2unpack ${SROOT}/${x}
            ;;
      *)
            echo "Archive format not recognized."
            exit
            ;;
esac                                      



在上例中,bash 首先擴展 "${x##*.}"。在代碼中,"$x" 是文件的名稱,"${x##.*}" 除去文件中最后句點后文本之外的所有文本。然后,bash 將產(chǎn)生的字符串與 "" 左邊列出的值做比較。在本例中,"${x##.*}" 先與 "gz" 比較,然后是 "bz2",最后是 "*"。如果 "${x##.*}" 與這些字符串或模式中的任何一個匹配,則執(zhí)行緊接 "" 之后的行,直到 ";;" 為止,然后 bash 繼續(xù)執(zhí)行結(jié)束符 "esac" 之后的行。如果不匹配任何模式或字符串,則不執(zhí)行任何代碼行,在這個特殊的代碼片段中,至少要執(zhí)行一個代碼塊,因為任何不與 "gz" 或 "bz2" 匹配的字符串都將與 "*" 模式匹配。

函數(shù)與名稱空間
在 bash 中,甚至可以定義與其它過程語言(如 Pascal 和 C)類似的函數(shù)。在 bash 中,函數(shù)甚至可以使用與腳本接收命令行自變量類似的方式來接收自變量。讓我們看一下樣本函數(shù)定義,然后再從那里繼續(xù):




tarview() {
     echo -n "Displaying contents of $1 "
     if [ ${1##*.} = tar ]
then
         echo "(uncompressed tar)"
         tar tvf $1
     elif [ ${1##*.} = gz ]
then
         echo "(gzip-compressed tar)"
         tar tzvf $1
     elif [ ${1##*.} = bz2 ]
then
         echo "(bzip2-compressed tar)"
         cat $1 | bzip2 -d | tar tvf -
fi
}



另一種情況
可以使用 "case" 語句來編寫上面的代碼。您知道如何編寫嗎?


我們在上面定義了一個名為 "tarview" 的函數(shù),它接收一個自變量,即某種類型的 tar 文件。在執(zhí)行該函數(shù)時,它確定自變量是哪種 tar 文件類型(未壓縮的、gzip 壓縮的或 bzip2 壓縮的),打印一行信息性消息,然后顯示 tar 文件的內(nèi)容。應(yīng)該如下調(diào)用上面的函數(shù)(在輸入、粘貼或找到該函數(shù)后,從腳本或命令行調(diào)用它):



$ tarview shorten.tar.gz
Displaying contents of shorten.tar.gz (gzip-compressed tar)
drwxr-xr-x ajr/abbot         0 1999-02-27 16:17 shorten-2.3a/
-rw-r--r-- ajr/abbot      1143 1997-09-04 04:06 shorten-2.3a/Makefile
-rw-r--r-- ajr/abbot      1199 1996-02-04 12:24 shorten-2.3a/INSTALL
-rw-r--r-- ajr/abbot       839 1996-05-29 00:19 shorten-2.3a/LICENSE
....  



交互地使用它們
別忘了,可以將函數(shù)(如上面的函數(shù))放在 ~/.bashrc 或 ~/.bash_profile 中,以便在 bash 中隨時使用它們。


如您所見,可以使用與引用命令行自變量同樣的機制來在函數(shù)定義內(nèi)部引用自變量。另外,將把 "$#" 宏擴展成包含自變量的數(shù)目。唯一可能不完全相同的是變量 "$0",它將擴展成字符串 "bash"(如果從 shell 交互運行函數(shù))或調(diào)用函數(shù)的腳本名稱。

名稱空間
經(jīng)常需要在函數(shù)中創(chuàng)建環(huán)境變量。雖然有可能,但是還有一個技術(shù)細節(jié)應(yīng)該了解。在大多數(shù)編譯語言(如 C)中,當(dāng)在函數(shù)內(nèi)部創(chuàng)建變量時,變量被放置在單獨的局部名稱空間中。因此,如果在 C 中定義一個名為 myfunction 的函數(shù),并在該函數(shù)中定義一個名為 "x" 的自變量,則任何名為 "x" 的全局變量(函數(shù)之外的變量)將不受它的印象,從而消除了負作用。

在 C 中是這樣,但在 bash 中卻不是。在 bash 中,每當(dāng)在函數(shù)內(nèi)部創(chuàng)建環(huán)境變量,就將其添加到 全局名稱空間。這意味著,該變量將重寫函數(shù)之外的全局變量,并在函數(shù)退出之后繼續(xù)存在:



#!/usr/bin/env bash

myvar="hello"

myfunc() {

     myvar="one two three"
     for x in $myvar
     do
         echo $x
     done
}

myfunc

echo $myvar $x



運行此腳本時,它將輸出 "one two three three",這顯示了在函數(shù)中定義的 "$myvar" 如何影響全局變量 "$myvar",以及循環(huán)控制變量 "$x" 如何在函數(shù)退出之后繼續(xù)存在(如果 "$x" 全局變量存在,也將受到影響)。

在這個簡單的例子中,很容易找到該錯誤,并通過使用其它變量名來改正錯誤。但這不是正確的方法,解決此問題的最好方法是通過使用 "local" 命令,在一開始就預(yù)防影響全局變量的可能性。當(dāng)使用 "local" 在函數(shù)內(nèi)部創(chuàng)建變量時,將把它們放在 局部名稱空間中,并且不會影響任何全局變量。這里演示了如何實現(xiàn)上述代碼,以便不重寫全局變量:




#!/usr/bin/env bash

myvar="hello"

myfunc() {
     local x
     local myvar="one two three"
     for x in $myvar
     do
         echo $x
     done
}

myfunc

echo $myvar $x



此函數(shù)將輸出 "hello" -- 不重寫全局變量 "$myvar","$x" 在 myfunc 之外不繼續(xù)存在。在函數(shù)的第一行,我們創(chuàng)建了以后要使用的局部變量 x,而在第二個例子 (local myvar="one two three"" 中,我們創(chuàng)建了局部變量 myvar, 同時 為其賦值。在將循環(huán)控制變量定義為局部變量時,使用第一種形式很方便,因為不允許說:"for local x in $myvar"。此函數(shù)不影響任何全局變量,鼓勵您用這種方式設(shè)計所有的函數(shù)。只有在明確希望要修改全局變量時,才 不應(yīng)該使用 "local"。

結(jié)束語
我們已經(jīng)學(xué)習(xí)了最基本的 bash 功能,現(xiàn)在要看一下如何基于 bash 開發(fā)整個應(yīng)用程序。下一部分正要講到。再見!

參考資料

您可以參閱本文在 developerWorks 全球站點上的 英文原文.


閱讀介紹性的 bash 文章, developerWorks上的“ Bash 實例,第 1 部分”


訪問 GNU's bash 主頁


查看 bash online reference manual
作者: mocou    時間: 2005-09-08 14:19
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
第三部份呢?一次轉(zhuǎn)完吧?
作者: dinlin2000    時間: 2005-09-08 14:51
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
Bash 實例,第 3 部分   
  


   
內(nèi)容:

進入 ebuild 系統(tǒng)

為什么選擇 bash?

構(gòu)建過程回顧

使代碼通用

添加功能性

使代碼模塊化

配置文件

什么是并行 make?

結(jié)束語

參考資料  

關(guān)于作者

對本文的評價



訂閱:

developerWorks 時事通訊






探討 ebuild 系統(tǒng)

Daniel Robbins
總裁兼 CEO, Gentoo Technologies, Inc.
2000 年 5 月

Daniel Robbins 在其最后一篇 Bash實例文章中詳細講述了 Gentoo Linux ebuild 系統(tǒng),這個展示 bash能力的極佳范例。循序漸進地,他為您展示如何實現(xiàn) ebuild系統(tǒng),并觸及很多方便的 bash技術(shù)和設(shè)計策略。在本文末尾,您將很好地掌握制造完全基于 bash的應(yīng)用所涉及的技術(shù),并開始為自己的自動構(gòu)建系統(tǒng)編碼。
進入 ebuild 系統(tǒng)
我真是一直期待著這第三篇、也是最后一篇 Bash 實例文章,因為既然已經(jīng)在 第 1 篇和 第 2 篇 中講述了 bash 編程基礎(chǔ),就可以集中講述象 bash 應(yīng)用開發(fā)和程序設(shè)計這樣更高級的主題。在本文中,將通過我花了許多時間來編碼和細化的項目,Gentoo Linux ebuild 系統(tǒng),來給您大量實際的、現(xiàn)實世界的 bash 開發(fā)經(jīng)驗。

我是 Gentoo Linux(目前還是 beta 版的下一代 Linux OS)的首席設(shè)計師。我的主要責(zé)任之一就是確保所有二進制包(類似于 RPM)都正確創(chuàng)建并一起使用。正如您可能知道的,標(biāo)準(zhǔn) Linux 系統(tǒng)不是由一棵統(tǒng)一的源樹組成(象 BSD),而實際上是由超過 25 個協(xié)同工作的核心包組成。這其中包括:

包  描述  
linux 實際內(nèi)核
util-linux 與 Linux 相關(guān)的雜項程序集合
e2fsprogs 與 ext2 文件系統(tǒng)相關(guān)的實用程序集合
glibc GNU C 庫

每個包都位于各自的 tar 壓縮包中,并由不同的獨立開發(fā)人員或開發(fā)小組維護。要創(chuàng)建一個發(fā)行版,必須對每個包分別進行下載、編譯和打包處理。每次要修復(fù)、升級或改進包時,都必須重復(fù)編譯和打包步驟(并且,包確實更新得很快)。為了幫助消除創(chuàng)建和更新包所涉及的重復(fù)步驟,我創(chuàng)建了 ebuild 系統(tǒng),該系統(tǒng)幾乎全用 bash 編寫。為了增加您的 bash 知識,我將循序漸進地為您演示如何實現(xiàn)該 ebuild 系統(tǒng)的解包和編譯部分。在解釋每一步時,還將討論為什么要作出某些設(shè)計決定。在本文末尾,您不僅將極好地掌握大型 bash 編程項目,還實現(xiàn)了完整自動構(gòu)建系統(tǒng)的很大一部分。

為什么選擇 bash?
Bash 是 Gentoo Linux ebuild 系統(tǒng)的基本組件。選擇它做為 ebuild 的主要語言有幾個原因。首先,其語法不復(fù)雜,并且為人們所熟悉,這特別適合于調(diào)用外部程序。自動構(gòu)建系統(tǒng)是自動調(diào)用外部程序的“膠合代碼”,而 bash 非常適合于這種類型的應(yīng)用。第二,Bash 對函數(shù)的支持允許 ebuild 系統(tǒng)使用模塊化、易于理解的代碼。第三,ebuild 系統(tǒng)利用了 bash 對環(huán)境變量的支持,允許包維護人員和開發(fā)人員在運行時對其進行方便的在線配置。

構(gòu)建過程回顧
在討論 ebuild 系統(tǒng)之前,讓我們回顧一下編譯和安裝包都牽涉些什么。例如,讓我們看一下 "sed" 包,這個作為所有 Linux 版本一部分的標(biāo)準(zhǔn) GNU 文本流編輯實用程序。首先,下載源代碼 tar 壓縮包 (sed-3.02.tar.gz)(請參閱 參考資料 )。我們將把這個檔案存儲在 /usr/src/distfiles 中,將使用環(huán)境變量 "$DISTDIR" 來引用該目錄。"$DISTDIR" 是所有原始源代碼 tar 壓縮包所在的目錄,它是一個大型源代碼庫。

下一步是創(chuàng)建名為 "work" 的臨時目錄,該目錄存放已經(jīng)解壓的源代碼。以后將使用 "$WORKDIR" 環(huán)境變量引用該目錄。要做到這點,進入有寫權(quán)限的目錄,然后輸入:

將 sed 解壓縮到臨時目錄

$ mkdir work
$ cd work
$ tar xzf /usr/src/distfiles/sed-3.02.tar.gz



然后,解壓縮 tar 壓縮包,創(chuàng)建一個包含所有源代碼、名為 sed-3.02 的目錄。以后將使用環(huán)境變量 "$SRCDIR" 引用 sed-3.02 目錄。要編譯程序,輸入:

將 sed 解壓縮到臨時目錄

$ cd sed-3.02
$ ./configure --prefix=/usr
(autoconf 生成適當(dāng)?shù)?make 文件,這要花一些時間)

$ make

(從源代碼編譯包,也要花一點時間)




因為在本文中只講述解包和編譯步驟,所以將略過 "make install" 步驟。如果要編寫 bash 腳本來執(zhí)行所有這些步驟,則代碼可能類似于:

要執(zhí)行解包/編譯過程的樣本 bash 腳本

#!/usr/bin/env bash

if [ -d work ]
then
# remove old work directory if it exists
    rm -rf work
fi
mkdir work
cd work
tar xzf /usr/src/distfiles/sed-3.02.tar.gz
cd sed-3.02
./configure --prefix=/usr
make



使代碼通用
雖然可以使用這個自動編譯腳本,但它不是很靈活。基本上,bash 腳本只包含在命令行輸入的所有命令列表。雖然可以使用這種解決方案,但是,最好做一個只通過更改幾行就可以快速解包和編譯任何包的適用腳本。這樣,包維護人員將新包添加到發(fā)行版所需的工作就大為減少。讓我們先嘗試一下使用許多不同的環(huán)境變量來完成,使構(gòu)建腳本更加適用:

新的、更通用的腳本

#!/usr/bin/env bash

# P is the package name

P=sed-3.02

# A is the archive name

A=${P}.tar.gz

export ORIGDIR=`pwd`
export WORKDIR=${ORIGDIR}/work
export SRCDIR=${WORKDIR}/${P}

if [ -z "$DISTDIR" ]
then
    # set DISTDIR to /usr/src/distfiles if not already set
    DISTDIR=/usr/src/distfiles
fi
export DISTDIR

if [ -d ${WORKDIR} ]
then   
    # remove old work directory if it exists
    rm -rf ${WORKDIR}
fi

mkdir ${WORKDIR}
cd ${WORKDIR}
tar xzf ${DISTDIR}/${A}
cd ${SRCDIR}
./configure --prefix=/usr
make



已經(jīng)向代碼中添加了很多環(huán)境變量,但是,它基本上還是執(zhí)行同一功能。但是,如果現(xiàn)在要要編譯任何標(biāo)準(zhǔn)的 GNU 基于 autoconf 的源代碼 tar 壓縮包,只需簡單地將該文件復(fù)制到一個新文件(用合適的名稱來反映它所編譯的新包名),然后將 "$A" 和 "$P" 的值更改成新值即可。所有其它環(huán)境變量都自動調(diào)整成正確設(shè)置,并且腳本按預(yù)想工作。雖然這很方便,但是代碼還有改進余地。這段代碼比我們開始創(chuàng)建的 "transcript" 腳本要長很多。既然任何編程項目的目標(biāo)之一是減少用戶復(fù)雜度,所以最好大幅度縮短代碼,或者至少更好地組織代碼?梢杂靡粋巧妙的方法來做到這點 -- 將代碼拆成兩個單獨文件。將該文件存為 "sed-3.02.ebuild":

sed-3.02.ebuild

#the sed ebuild file -- very simple!
P=sed-3.02
A=${P}.tar.gz
   



第一個文件不重要,只包含那些必須在每個包中配置的環(huán)境變量。下面是第二個文件,它包含操作的主要部分。將它存為 "ebuild",并使它成為可執(zhí)行文件:

ebuild 腳本

#!/usr/bin/env bash


if [ $# -ne 1 ]
then
    echo "one argument expected."
    exit 1
fi

if [ -e "$1" ]
then
    source $1
else
    echo "ebuild file $1 not found."
    exit 1
fi

export ORIGDIR=`pwd`
export WORKDIR=${ORIGDIR}/work
export SRCDIR=${WORKDIR}/${P}

if [ -z "$DISTDIR" ]
then
    # set DISTDIR to /usr/src/distfiles if not already set
    DISTDIR=/usr/src/distfiles
fi
export DISTDIR

if [ -d ${WORKDIR} ]
then   
    # remove old work directory if it exists
    rm -rf ${WORKDIR}
fi

mkdir ${WORKDIR}
cd ${WORKDIR}
tar xzf ${DISTDIR}/${A}
cd ${SRCDIR}
./configure --prefix=/usr
make



既然已經(jīng)將構(gòu)建系統(tǒng)拆成兩個文件,我敢打賭,您一定在想它的工作原理;旧,要編譯 sed,輸入:

$ ./ebuild sed-3.02.ebuild


當(dāng)執(zhí)行 "ebuild" 時,它首先試圖 "source" 變量 "$1"。這是什么意思?還記得 前一篇文章 所講的嗎:"$1" 是第一個命令行自變量 -- 在這里,是 "sed-3.02.ebuild"。在 bash 中,"source" 命令從文件中讀入 bash 語句,然后執(zhí)行它們,就好象它們直接出現(xiàn)在 "source" 命令所在的文件中一樣。因此,"source ${1}" 導(dǎo)致 "ebuild" 腳本執(zhí)行在 "sed-3.02.ebuild" 中定義 "$P" 和 "$A" 的命令。這種設(shè)計更改確實方便,因為如果要編譯另一個程序,而不是 sed,可以簡單地創(chuàng)建一個新的 .ebuild 文件,然后將其作為自變量傳遞給 "ebuild" 腳本。通過這種方式,.ebuild 文件最終非常簡單,而將 ebuild 系統(tǒng)復(fù)雜的操作部分存在一處,即 "ebuild" 腳本中。通過這種方式,只需編輯 "ebuild" 腳本就可以升級或增強 ebuild 系統(tǒng),同時將實現(xiàn)細節(jié)保留在 ebuild 文件之外。這里有一個 gzip 的樣本 ebuild 文件:

gzip-1.2.4a.ebuild

#another really simple ebuild script!
P=gzip-1.2.4a
A=${P}.tar.gz




添加功能性
好,我們正在取得進展。但是,我還想添加某些額外功能性。我希望 ebuild 腳本再接受一個命令行自變量:"compile"、"unpack" 或 "all"。這個命令行自變量告訴 ebuild 腳本要執(zhí)行構(gòu)建過程的哪一步。通過這種方式,可以告訴 ebuild 解包檔案,但不進行編譯(以便在開始編譯之前查看源代碼檔案)。要做到這點,將添加一條 case 語句,該語句將測試 "$2",然后根據(jù)其值執(zhí)行不同操作。代碼如下:

ebuild,修定本 2

#!/usr/bin/env bash

if [ $# -ne 2 ]
then
    echo "lease specify two args - .ebuild file and unpack, compile or all"
    exit 1
fi


if [ -z "$DISTDIR" ]
then
    # set DISTDIR to /usr/src/distfiles if not already set
    DISTDIR=/usr/src/distfiles
fi
export DISTDIR

ebuild_unpack() {
    #make sure we're in the right directory
    cd ${ORIGDIR}
   
    if [ -d ${WORKDIR} ]
    then   
        rm -rf ${WORKDIR}
    fi

    mkdir ${WORKDIR}
    cd ${WORKDIR}
    if [ ! -e ${DISTDIR}/${A} ]
    then
        echo "${DISTDIR}/${A} does not exist.  Please download first."
        exit 1
    fi   
    tar xzf ${DISTDIR}/${A}
    echo "Unpacked ${DISTDIR}/${A}."
    #source is now correctly unpacked
}


ebuild_compile() {
   
    #make sure we're in the right directory
    cd ${SRCDIR}
    if [ ! -d "${SRCDIR}" ]
    then
        echo "${SRCDIR} does not exist -- please unpack first."
        exit 1
        fi
    ./configure --prefix=/usr
    make     
}

export ORIGDIR=`pwd`
export WORKDIR=${ORIGDIR}/work

if [ -e "$1" ]
then
    source $1
else
    echo "Ebuild file $1 not found."
    exit 1
fi

export SRCDIR=${WORKDIR}/${P}

case "${2}" in
    unpack)
        ebuild_unpack
        ;;
    compile)
        ebuild_compile
        ;;
    all)
        ebuild_unpack
        ebuild_compile
        ;;
    *)
        echo "lease specify unpack, compile or all as the second arg"
        exit 1
        ;;
esac



已經(jīng)做了很多改動,下面來回顧一下。首先,將編譯和解包步驟放入各自的函數(shù)中,其函數(shù)名分別為 ebuild_compile() 和 ebuild_unpack()。這是個好的步驟,因為代碼正變得越來越復(fù)雜,而新函數(shù)提供了一定的模塊性,使代碼更有條理。在每個函數(shù)的第一行,顯式 "cd" 到想要的目錄,因為,隨著代碼變得越來越模塊化而不是線形化,出現(xiàn)疏忽而在錯誤的當(dāng)前工作目錄中執(zhí)行函數(shù)的可能性也變大。"cd" 命令顯式地使我們處于正確的位置,并防止以后出現(xiàn)錯誤 - 這是重要的步驟,特別是在函數(shù)中刪除文件時更是如此。

另外,還在 ebuild_compile() 函數(shù)的開始處添加了一個有用的檢查。現(xiàn)在,它檢查以確保 "$SRCDIR" 存在,如果不存在,則打印一條告訴用戶首先解包檔案然后退出的錯誤消息。如果愿意,可以改變這種行為,以便在 "$SRCDIR" 不存在的情況下,ebuild 腳本將自動解包源代碼檔案?梢杂靡韵麓a替換 ebuild_compile() 來做到這點:

ebuild_compile() 上的新代碼

ebuild_compile() {
    #make sure we're in the right directory  
    if [ ! -d "${SRCDIR}" ]
    then
        ebuild_unpack
        fi
    cd ${SRCDIR}
    ./configure --prefix=/usr
    make     
}



ebuild 腳本第二版中最明顯的改動之一就是代碼末尾新的 case 語句。這條 case 語句只是檢查第二個命令行自變量,然后根據(jù)其值執(zhí)行正確操作。如果現(xiàn)在輸入:

$ ebuild sed-3.02.ebuild


就會得到一條錯誤消息。現(xiàn)在需要告訴 ebuild 做什么,如下所示:

$ ebuild sed-3.02.ebuild unpack




$ ebuild sed-3.02.ebuild compile




$ ebuild sed-3.02.ebuild all


如果提供上面所列之外的第二個命令行自變量,將得到一條錯誤消息(* 子句),然后,程序退出。

使代碼模塊化
既然代碼很高級并且實用,您可能很想創(chuàng)建幾個更高級的 ebuild 腳本,以解包和編譯所喜愛的程序。如果這樣做,遲早會遇到一些不使用 autoconf ("./configure" 的源代碼,或者可能遇到其它使用非標(biāo)準(zhǔn)編譯過程的腳本。需要再對 ebuild 系統(tǒng)做一些改動,以適應(yīng)這些程序。但是在做之前,最好先想一下如何完成。

將 "./configure --prefix=/usr; make" 硬編碼到編譯階段的妙處之一是:大多數(shù)時候,它可以正確工作。但是,還必須使 ebuild 系統(tǒng)適應(yīng)那些不使用 autoconf 或正常 make 文件的源代碼。要解決這個問題,建議 ebuild 腳本缺省執(zhí)行以下操作:

如果在 "${SRCDIR}" 中有一個配置腳本,則按如下執(zhí)行它:
./configure --prefix=/usr
否則,跳過這步。
執(zhí)行以下命令:
make
既然 ebuild 只在 configure 實際存在時才運行它,現(xiàn)在可以自動地適應(yīng)那些不使用 autoconf 但有標(biāo)準(zhǔn) make 文件的程序。但是,在簡單的 "make" 對某些源代碼無效時該怎么辦?需要一些處理這些情況的特定代碼來覆蓋合理的缺省值。要做到這一點,將把 ebuild_compile() 函數(shù)轉(zhuǎn)換成兩個函數(shù)。第一個函數(shù)(可將其當(dāng)成“父”函數(shù))的名稱仍是 ebuild_compile()。但是,將有一個名為 user_compile() 的新函數(shù),該函數(shù)只包含合理的缺省操作:

拆成兩個函數(shù)的 ebuild_compile()

user_compile() {
    #we're already in ${SRCDIR}
    if [ -e configure ]
    then
        #run configure script if it exists
        ./configure --prefix=/usr
    fi
    #run make
    make
}         

ebuild_compile() {
    if [ ! -d "${SRCDIR}" ]
    then
        echo "${SRCDIR} does not exist -- please unpack first."
        exit 1
    fi
    #make sure we're in the right directory  
    cd ${SRCDIR}
    user_compile
}



現(xiàn)在這樣做的原因可能還不是很明顯,但是,再忍耐一下。雖然這段代碼與 ebuild 前一版的工作方式幾乎相同,但是現(xiàn)在可以做一些以前無法做的 -- 可以在 sed-3.02.ebuild 中覆蓋 user_compile()。因此,如果缺省的 user_compile() 不滿足要求,可以在 .ebuild 文件中定義一個新的,使其包含編譯包所必需的命令。例如,這里有一個 e2fsprogs-1.18 的 ebuild 文件,它需要一個略有不同的 "./configure" 行:

e2fsprogs-1.18.ebuild

#this ebuild file overrides the default user_compile()
P=e2fsprogs-1.18
A=${P}.tar.gz

user_compile() {
       ./configure --enable-elf-shlibs
       make
}



現(xiàn)在,將完全按照我們希望的方式編譯 e2fsprogs。但是,對于大多數(shù)包來說,可以省略 .ebuild 文件中的任何定制 user_compile() 函數(shù),而使用缺省的 user_compile() 函數(shù)。

ebuild 腳本又怎樣知道要使用哪個 user_compile() 函數(shù)呢?實際上,這很簡單。ebuild 腳本中,在執(zhí)行 e2fsprogs-1.18.ebuild 文件之前定義缺省 user_compile() 函數(shù)。如果在 e2fsprogs-1.18.ebuild 中有一個 user_compile(),則它覆蓋前面定義的缺省版本。如果沒有,則使用缺省 user_compile() 函數(shù)。

這是好工具,我們已經(jīng)添加了很多靈活性,而無需任何復(fù)雜代碼(如果不需要的話)。在這里就不講了,但是,還應(yīng)該對 ebuild_unpack() 做類似修改,以便用戶可以覆蓋缺省解包過程。如果要做任何修補,或者文件包含在多個檔案中,則這非常方便。還有個好主意是修改解包代碼,以便它可以缺省識別由 bzip2 壓縮的 tar 壓縮包。

配置文件
目前為止,已經(jīng)講了很多不方便的 bash 技術(shù),現(xiàn)在再講一個。通常,如果程序在 /etc 中有一個配置文件是很方便的。幸運的是,用 bash 做到這點很容易。只需創(chuàng)建以下文件,然后并其存為 /etc/ebuild.conf 即可:

/ect/ebuild.conf

# /etc/ebuild.conf: set system-wide ebuild options in this file

# MAKEOPTS are options passed to make
MAKEOPTS="-j2"



在該例中,只包括了一個配置選項,但是,您可以包括更多。bash 的一個妙處是:通過執(zhí)行該文件,就可以對它進行語法分析。在大多數(shù)解釋型語言中,都可以使用這個設(shè)計竅門。執(zhí)行 /etc/ebuild.conf 之后,在 ebuild 腳本中定義 "$MAKEOPTS"。將利用它允許用戶向 make 傳遞選項。通常,將使用該選項來允許用戶告訴 ebuild 執(zhí)行 并行 make。

什么是并行 make?
為了提高多處理器系統(tǒng)的編譯速度,make 支持并行編譯程序。這意味著,make 同時編譯用戶指定數(shù)目的源文件(以便使用多處理器系統(tǒng)中的額外處理器),而不是一次只編譯一個源文件。通過向 make 傳遞 -j # 選項來啟用并行 make,如下所示:

make -j4 MAKE="make -j4"


這行代碼指示 make 同時編譯四個程序。 MAKE="make -j4" 自變量告訴 make,向其啟動的任何子 make 進程傳遞 -j4 選項。

這里是 ebuild 程序的最終版本:

ebuild,最終版本

#!/usr/bin/env bash

if [ $# -ne 2 ]
then
    echo "lease specify ebuild file and unpack, compile or all"
    exit 1
fi

source /etc/ebuild.conf

if [ -z "$DISTDIR" ]
then
    # set DISTDIR to /usr/src/distfiles if not already set
    DISTDIR=/usr/src/distfiles
fi
export DISTDIR

ebuild_unpack() {
    #make sure we're in the right directory
    cd ${ORIGDIR}
   
    if [ -d ${WORKDIR} ]
    then   
        rm -rf ${WORKDIR}
    fi

    mkdir ${WORKDIR}
    cd ${WORKDIR}
    if [ ! -e ${DISTDIR}/${A} ]
    then
        echo "${DISTDIR}/${A} does not exist.  Please download first."
        exit 1
    fi
    tar xzf ${DISTDIR}/${A}
    echo "Unpacked ${DISTDIR}/${A}."
    #source is now correctly unpacked
}

user_compile() {
    #we're already in ${SRCDIR}
    if [ -e configure ]
    then
        #run configure script if it exists
        ./configure --prefix=/usr
    fi
        #run make
        make $MAKEOPTS MAKE="make $MAKEOPTS"  
}

ebuild_compile() {
    if [ ! -d "${SRCDIR}" ]
    then
        echo "${SRCDIR} does not exist -- please unpack first."
        exit 1
    fi
        #make sure we're in the right directory  
    cd ${SRCDIR}
    user_compile
}

export ORIGDIR=`pwd`
export WORKDIR=${ORIGDIR}/work

if [ -e "$1" ]
then
    source $1
else
    echo "Ebuild file $1 not found."
    exit 1
fi

export SRCDIR=${WORKDIR}/${P}

case "${2}" in
    unpack)
        ebuild_unpack
        ;;
    compile)
        ebuild_compile
        ;;
    all)
        ebuild_unpack
        ebuild_compile
        ;;
    *)
        echo "lease specify unpack, compile or all as the second arg"
        exit 1
        ;;
esac



請注意,在文件的開始部分執(zhí)行 /etc/ebuild.conf。另外,還要注意,在缺省 user_compile() 函數(shù)中使用 "$MAKEOPTS"。您可能在想,這管用嗎 - 畢竟,在執(zhí)行實際上事先定義 "$MAKEOPTS" 的 /etc/ebuild.conf 之前,我們引用了 "$MAKEOPTS"。對我們來說幸運的是,這沒有問題,因為變量擴展只在執(zhí)行 user_compile() 時才發(fā)生。在執(zhí)行 user_compile() 時,已經(jīng)執(zhí)行了 /etc/ebuild.conf,并且 "$MAKEOPTS" 也被設(shè)置成正確的值。

結(jié)束語
本文已經(jīng)講述了很多 bash 編程技術(shù),但是,只觸及到 bash 能力的一些皮毛。例如,Gentoo Linux ebuild 產(chǎn)品不僅自動解包和編譯每個包,還可以:

如果在 "$DISTDIR" 沒找到源代碼,則自動下載
通過使用 MD5 消息摘要,驗證源代碼沒有受到破壞
如果請求,則將編譯過的應(yīng)用程序安裝到正在使用的文件系統(tǒng),并記錄所有安裝的文件,以便日后可以方便地將包卸載。
如果請求,則將編譯過的應(yīng)用程序打包成 tar 壓縮包(以您希望的形式壓縮),以便以后可以在另一臺計算機上,或者在基于 CD 的安裝過程中(如果在構(gòu)建發(fā)行版 CD)安裝。
另外,ebuild 系統(tǒng)產(chǎn)品還有幾個全局配置選項,允許用戶指定選項,例如在編譯過程中使用什么優(yōu)化標(biāo)志,在那些支持它的包中是否應(yīng)該缺省啟用可選的包支持(例如 GNOME 和 slang)。

顯然,bash 可以實現(xiàn)的功能遠比本系列文章中所觸及的要多。關(guān)于這個不可思議的工具,希望您已經(jīng)學(xué)到了很多,并鼓舞您使用 bash 來加快和增強開發(fā)項目。

參考資料

您可以參閱本文在 developerWorks 全球站點上的 英文原文.


從 ftp://ftp.gnu.org/pub/gnu/sed 下載源代碼 tar 壓縮包 (sed-3.02.tar.gz)。


在 developerWorks上閱讀 “Bash 實例:第 1 部分”。


在 developerWorks上閱讀 “Bash 實例:第 2 部分”。


造訪 Gentoo Project 主頁。


造訪 GNU 的 bash 主頁。


查看 bash online reference manual。


關(guān)于作者
Daniel Robbins 居住在美國新墨西哥州 Albuquerque。他是 Gentoo 項目 的總設(shè)計師,Gentoo Technologies, Inc. 的 CEO,Linux Advanced Multimedia Project (LAMP) 的顧問,Macmillan 書籍 Caldera OpenLinux Unleashed、 SuSE Linux Unleased和 Samba Unleashed 的作者。Daniel 自小學(xué)二年級起就與計算機結(jié)下不解之緣,那時他首先接觸的是 Logo 程序語言,并沉溺于 Pac-Man 游戲中。這也許就是他至今仍擔(dān)任 SONY Electronic Publishing/ Psygnosis 首席圖形設(shè)計師的原因所在。Daniel 喜歡與妻子 Mary 一起共渡時光,他們的孩子即將誕生。可通過 drobbins@gentoo.org 與 Daniel Robbins 聯(lián)系。
作者: 秋池飛葉    時間: 2005-09-08 18:46
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
感謝
作者: joefun    時間: 2005-09-09 18:51
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我有pdf的,有沒有g(shù)gmm想要,留個email
作者: ldqqxf    時間: 2005-09-09 20:35
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我想要
e-mail: ldqqxf@yahoo.com.cn
作者: dingyi129    時間: 2005-09-09 21:33
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
dingyishell@gmail.com

謝謝啦!
作者: suyilala    時間: 2005-09-10 11:30
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
suyila1980@hotmail.com
謝了
作者: joefun    時間: 2005-09-10 15:35
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
以上3位已發(fā)
作者: kenail2002    時間: 2005-09-11 01:46
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
給俺也發(fā)一份
kenail2002@163.com
謝了。
作者: oyjcq    時間: 2005-09-12 15:29
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
chenq918@126.com
謝謝
作者: creat7151    時間: 2005-09-12 15:41
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
creat7151@hotmail.com
多謝了
作者: dingyi129    時間: 2005-09-12 15:42
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我收到啦,謝謝
作者: afoxwwk    時間: 2005-09-12 16:43
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
發(fā)一份俾我啦,唔該!
afoxwwk@163.com
作者: yuyuyou    時間: 2005-09-12 19:00
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
yuyuyou_001@163.com

能給我發(fā)一個嗎?

謝謝了!
作者: dingyi129    時間: 2005-09-12 19:22
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
樓上的2位我?guī)蜆侵靼l(fā)了
作者: yuyuyou    時間: 2005-09-12 20:04
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
dingyi129,已收到!

感謝!     
作者: dingyi129    時間: 2005-09-12 20:32
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
原帖由 "yuyuyou" 發(fā)表:
dingyi129,已收到!

感謝!     


我也是收到樓主給我發(fā)的
就發(fā)給大家嘍
作者: pxm3620    時間: 2005-09-12 22:05
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
pxm3620@hotmail.com
謝了
作者: alexander_lu    時間: 2005-09-13 17:33
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
能不能給我一份,謝謝!
lfejs@sohu.com
作者: luoysx    時間: 2005-09-14 10:46
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
luoysx@yahoo.com.cn   先謝謝了
作者: xy-coordinate    時間: 2005-09-14 10:51
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我也想要
xy_coordinate@sina.com
作者: honbj    時間: 2005-09-14 10:53
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
一聲嘆息
作者: ghbspecial    時間: 2005-09-14 22:20
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
很好啊,,希望可以給發(fā)一下:ghbspecial@163.com
作者: jlus    時間: 2005-09-15 01:31
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我也想要
jlus@163.com
作者: joefun    時間: 2005-09-19 07:33
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
幾天沒來了,各位要的文檔已發(fā),希望喜歡shell的朋友共同進步,
我的msn:joefun_xm@msn.com
各位多多指教!   
作者: tobyhoo    時間: 2005-09-19 09:58
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
wanghong10012@163.com
thank you very much!!
作者: fgyq0830    時間: 2005-09-20 19:51
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我想要,謝了
email:     fgyq0830@yahoo.com.cn
作者: joefun    時間: 2005-09-20 21:41
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
以上兩位已發(fā)
作者: eric.xie    時間: 2005-09-20 23:32
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
樓主,也給我發(fā)一份吧!謝了!
作者: eric.xie    時間: 2005-09-20 23:33
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
樓主,也給我發(fā)一份吧!謝了!
eric.xie@126.com
作者: 大馬虎    時間: 2005-09-21 13:48
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
太好了。!
作者: joefun    時間: 2005-09-22 00:55
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
已經(jīng)發(fā)給eric.xie  了,
各位要是要的話就留下email,只要能上網(wǎng)我一定發(fā)。
作者: rogi1126    時間: 2005-09-22 08:57
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我也想要一份,謝謝樓主~~
zsj_1126@sina.com
作者: tonyfu    時間: 2005-09-22 11:06
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
775016@163.com

一定要發(fā)哦,,,,
作者: joefun    時間: 2005-09-22 12:46
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
已發(fā),請查收
作者: tonyfu    時間: 2005-09-22 12:51
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
3Q,,已收到,,,,,
作者: ylbaby2003    時間: 2005-09-22 13:00
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
yangliu@adtec.com.cn
作者: joefun    時間: 2005-09-22 19:18
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
樓上的已發(fā)
作者: eric.xie    時間: 2005-09-22 22:39
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
收到了,謝謝樓主。!
作者: joefun    時間: 2005-09-23 02:55
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
發(fā)文檔的不是樓主,只是覺得這個文檔還不錯,尤其是像我這樣的初學(xué)者;
故與各位xd共享
作者: rogi1126    時間: 2005-09-23 08:58
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
謝謝,收到!!     
作者: 89728972    時間: 2005-09-24 11:59
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
zhangjun_zzz@msn.com
謝謝樓主!
作者: waitwill    時間: 2005-09-26 09:35
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
dreamhat@163.com
還有我的,謝謝
作者: joefun    時間: 2005-09-26 12:59
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
以上兩位已發(fā)
作者: 一個小角色    時間: 2005-09-26 17:36
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
好東西啊
jxyhm007@163.com
作者: liroc    時間: 2005-09-28 09:24
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我也要,謝謝
lipeng.roc@163.com
這是好人
作者: joyaid    時間: 2005-09-28 15:30
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
我要!嗷嗷嗷嗷嗷嗷嗷嗷阿啊
作者: joefun    時間: 2005-09-29 19:29
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
已發(fā)
作者: yaop    時間: 2005-10-04 00:44
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
yaop@mail.ustc.edu.cn
非常感謝!!!!!!!!!
作者: 700724    時間: 2005-10-04 11:00
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
給我一份行嗎?
zypra@sohu.com
作者: joefun    時間: 2005-10-07 22:53
標(biāo)題: 『轉(zhuǎn)貼』Bash 實例
上兩樓的,已發(fā)!
作者: sqp1982    時間: 2005-10-08 18:27
提示: 作者被禁止或刪除 內(nèi)容自動屏蔽
作者: vip_xin    時間: 2006-02-14 10:55
我也想要一份,謝謝了
vip_xin@yahoo.com.cn
作者: xueyh    時間: 2006-02-14 11:37
提示: 作者被禁止或刪除 內(nèi)容自動屏蔽
作者: karlers    時間: 2006-02-14 13:32
看來今天要的人不少,我也來一份,謝謝。
shayue_ems@sohu.com
作者: ground    時間: 2006-02-15 10:52
不知道還能趕上不,謝謝!
gnosyhh@gmail.com
作者: fangzhang    時間: 2006-02-15 12:38
我也想要一份
zhouzhen1@gmail.com
謝謝了。
作者: lrz    時間: 2006-02-16 00:20
lurz@163.com
謝謝
作者: terry123    時間: 2006-02-16 23:50
標(biāo)題: 請發(fā)份給俺(pys_cn@126.com),
多謝多謝!!




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2