青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

興海北路

---男兒仗劍自橫行
<2009年3月>
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

統(tǒng)計(jì)

  • 隨筆 - 85
  • 文章 - 0
  • 評(píng)論 - 17
  • 引用 - 0

常用鏈接

留言簿(6)

隨筆分類

隨筆檔案

收藏夾

全是知識(shí)啊

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

shell編程范例之?dāng)?shù)值運(yùn)算

by falcon<zhangjinw@gmail.com>
2007-10-30

前言:
   
    從這個(gè)帖子開(kāi)始,打算結(jié)合自己平時(shí)的積累和進(jìn)一步的實(shí)踐,通過(guò)一些范例來(lái)介紹shell編程。因?yàn)榉独軌蚪o人以學(xué)有所用的感覺(jué),而且給人以動(dòng)手實(shí)踐 的機(jī)會(huì),從而激發(fā)人的學(xué)習(xí)熱情。考慮到易讀性,這里的范例將非常簡(jiǎn)單,但是實(shí)用,希望它們能夠成為你解決常規(guī)問(wèn)題的參照物或者是“茶余飯后”的小點(diǎn)心,當(dāng) 然這些“點(diǎn)心”肯定還有值得探討、優(yōu)化的地方。更復(fù)雜有趣的例子請(qǐng)參考《高級(jí)Bash腳本編程指南》(一本深入學(xué)習(xí)shell腳本藝術(shù)的書(shū)籍)。

    該計(jì)劃是上一篇帖子《在Linux下更高效的工作》的續(xù)。

    寫(xiě)這些東西的

Quote:

    目的:1)享受用shell解決問(wèn)題的樂(lè)趣 2)和朋友們一起交流和探討
    初步計(jì)劃:先零散地寫(xiě)些東西,之后再不斷補(bǔ)充,最后整理成冊(cè)。
    適合讀者:已經(jīng)熟悉linux基本知識(shí),比如文件系統(tǒng)結(jié)構(gòu)、常用命令行工具、shell編程基礎(chǔ)等。
    建議:大家在看這些范例的時(shí)候,參考網(wǎng)絡(luò)中流傳的《shell基礎(chǔ)十二篇》和《shell十三問(wèn)》,見(jiàn)ChinaUnix Shell討論區(qū)
    環(huán)境:如果沒(méi)有特別說(shuō)明,以后"shell編程范例"系列使用的shell將特指bash,版本在3.1.17以上。
    說(shuō)明:本序列的組織不是依據(jù)Shell語(yǔ)法,而是面向某些潛在的操作對(duì)象和操作本身,它們反應(yīng)了現(xiàn)實(shí)應(yīng)用。當(dāng)然,在這個(gè)過(guò)程當(dāng)中肯定會(huì)涉及到Shell的語(yǔ)法。另外,歡迎您對(duì)帖子里頭存在的問(wèn)題進(jìn)行批評(píng)指正,也歡迎您對(duì)一些范例進(jìn)行改進(jìn)。


shell編程范例之?dāng)?shù)值運(yùn)算

    這一篇打算討論一下shell編程中的基本數(shù)值運(yùn)算,這類運(yùn)算包括數(shù)值(包括整數(shù)和浮點(diǎn)數(shù))間的加減乘除冪求模等,產(chǎn)生指定范圍的隨機(jī)數(shù),產(chǎn)生指定范圍的數(shù)列等。
    貌似shell本身(shell本身是一個(gè)解釋程序,你可以在命令行打印SHELL變量找到當(dāng)前的shell程序)只可以完成整數(shù)運(yùn)算,一些復(fù)雜的運(yùn)算可 以通過(guò)外部命令實(shí)現(xiàn),比如expr,bc,awk等。至于隨機(jī)數(shù),shell可以通過(guò)RANDOM環(huán)境變量產(chǎn)生一個(gè)從0到32767的隨機(jī)數(shù),一些外部工 具,比如awk可以通過(guò)rand()函數(shù)產(chǎn)生隨機(jī)數(shù)。而seq命令可以用來(lái)產(chǎn)生一個(gè)數(shù)列。
    下面分別進(jìn)行介紹:

1、整數(shù)運(yùn)算

1.1 概要示例:對(duì)某個(gè)數(shù)加一

Quote:

$ i=0;
$ ((i++))
$ echo $i
1
$ let i++
$ echo $i
2
$ expr $i + 1
3
$ echo $i
2
$ echo $i 1 | awk '{printf $1+$2}'
3



    說(shuō)明:expr之后的$i,+,1之間有空格分開(kāi);awk后面的$1和$2分別指$i和1,即從左往右的第1個(gè)和第二個(gè)數(shù)。

用shell的內(nèi)置命令查看各個(gè)命令的類型如下:
Quote:

$ type type
type is a shell builtin
$ type let
let is a shell builtin
$ type expr
expr is hashed (/usr/bin/expr)
$ type bc
bc is hashed (/usr/bin/bc)
$ type awk
awk is /usr/bin/awk



    從上面的演示可以看出:let是shell內(nèi)置命令,其他幾個(gè)是外部命令,都在/usr/bin目錄下。而expr和bc因?yàn)槲覄傆眠^(guò),已經(jīng)加載在內(nèi)存的hash表中。這個(gè)結(jié)果將有助于我們理解下面范例的結(jié)果。

補(bǔ)充:如果查看不同命令的幫助
    對(duì)于let和type等shell內(nèi)置命令,可以通過(guò)shell的一個(gè)內(nèi)置命令help來(lái)查看相關(guān)幫助,而一些外部命令可以通過(guò)shell的一個(gè)外部命令man來(lái)查看幫助,用法諸如help let,man expr等。

1.2 范例演示:從1加到某個(gè)數(shù)值。

代碼:


Code:

[Ctrl+A Select All]



說(shuō)明:這里通過(guò)while [ 條件表達(dá)式 ]; do .... done循環(huán)來(lái)實(shí)現(xiàn)。-lt是小于號(hào)(<),具體見(jiàn)test命令的用法:man test。

如何執(zhí)行該腳本?

第一種辦法直接把腳本文件當(dāng)成子shell(bash)的一個(gè)參數(shù)傳入。
Quote:

$ bash calc.sh
$ type bash
bash is hashed (/bin/bash)



第二種辦法是通過(guò)bash的內(nèi)置命令.或source執(zhí)行。
Quote:

$ . ./calc.sh

$ source ./calc.sh
$ type .
. is a shell builtin
$ type source
source is a shell builtin



第三種辦法是修改文件為可執(zhí)行,直接在當(dāng)前shell下執(zhí)行。
Quote:

$ chmod ./calc.sh
$ ./calc.sh



下面,逐一演示用其他方法計(jì)算變量加一,即把((i++))行替換成下面的某一個(gè):
let i++;
i=$(expr $i + 1)
i=$(echo $i+1|bc)
i=$(echo "$i 1" | awk '{printf $1+$2;}')

比較計(jì)算時(shí)間如下:
Quote:

$ time calc.sh
10000

real    0m1.319s
user    0m1.056s
sys     0m0.036s
$ time calc_let.sh
10000

real    0m1.426s
user    0m1.176s
sys     0m0.032s
$  time calc_expr.sh
1000

real    0m27.425s
user    0m5.060s
sys     0m14.177s
$ time calc_bc.sh
1000

real    0m56.576s
user    0m9.353s
sys     0m24.618s
$ time ./calc_awk.sh
100

real    0m11.672s
user    0m2.604s
sys     0m2.660s



說(shuō)明:time命令可以用來(lái)統(tǒng)計(jì)命令執(zhí)行時(shí)間,這部分時(shí)間包括總的運(yùn)行時(shí)間,用戶空間執(zhí)行時(shí)間,內(nèi)核空間執(zhí)行時(shí)間,它通過(guò)ptrace系統(tǒng)調(diào)用實(shí)現(xiàn)。

總 結(jié):通過(guò)上面的比較,我們發(fā)現(xiàn)(())的運(yùn)算效率最高。而let作為shell內(nèi)置命令,效率也很高,但是expr,bc,awk的計(jì)算效率就比較低。所 以,在shell本身能夠完成相關(guān)工作的情況下,建議優(yōu)先使用shell本身提供的功能。但是shell本身好像無(wú)法完成浮點(diǎn)運(yùn)算,所以就需要外部命令的 幫助。

補(bǔ)充:let,expr,bc都可以用來(lái)求模,運(yùn)算符都是%,而let和bc可以用來(lái)求冪,運(yùn)算符不一樣,前者是**,后者是^。例如:

Quote:

//求模
$ expr 5 % 2
1
$ let i=5%2
$ echo $i
1
$ echo 5 % 2 | bc
1
$ ((i=5%2))
$ echo $i
1
//求冪
$ let i=5**2
$ echo $i
25
$ ((i=5**2))
$ echo $i
25
$ echo "5^2" | bc
25



2. 浮點(diǎn)運(yùn)算

let和expr都無(wú)法進(jìn)行浮點(diǎn)運(yùn)算,但是bc和awk可以。

2.1 概要示例:求1除以13,保留3位有效數(shù)字。

Quote:

$ echo "scale=3; 1/13"  | bc
.076
$ echo "1 13" | awk '{printf("%0.3f\n",$1/$2)}'
0.077



說(shuō)明:bc在進(jìn)行浮點(diǎn)運(yùn)算的時(shí)候需要指定小數(shù)點(diǎn)位數(shù),否則默認(rèn)為0,即進(jìn)行浮點(diǎn)運(yùn)算的時(shí)候,默認(rèn)求出的結(jié)果只保留整數(shù)。而awk在控制小數(shù)位數(shù)的時(shí)候非常靈活,僅僅通過(guò)printf的格式控制就可以實(shí)現(xiàn)。

補(bǔ)充:在用bc進(jìn)行運(yùn)算的時(shí)候,如果不指定scale,而在bc后加上-l選項(xiàng),也可以進(jìn)行浮點(diǎn)運(yùn)算,只不過(guò)這時(shí)的浮點(diǎn)運(yùn)算的小數(shù)點(diǎn)默認(rèn)是20位。例如:

Quote:

$ echo 1/13100 | bc -l
.00007633587786259541



2.2 范例演示:假如有這樣一組數(shù)據(jù),存放有某個(gè)村莊所有家庭的人數(shù)和月總收入,要求找出人均月收入最高的家庭。

在這里我隨機(jī)產(chǎn)生了一組數(shù)據(jù),文件名為income。
Quote:

1 3 4490
2 5 3896
3 4 3112
4 4 4716
5 4 4578
6 6 5399
7 3 5089
8 6 3029
9 4 6195
10 5 5145



說(shuō)明:上面的三列數(shù)據(jù)分別是家庭編號(hào)、家庭人數(shù)、家庭月總收入。
分析:為了求出月均收入最高的家庭,我們需要對(duì)后面兩列數(shù)進(jìn)行除法運(yùn)算,即求出每個(gè)家庭的月均收入,然后按照月均收入排序,找出收入最高的家庭。
實(shí)現(xiàn):



Code:

[Ctrl+A Select All]



說(shuō)明:
[ $# -lt 1 ]: 要求用戶至少收入一個(gè)參數(shù),$#是shell中傳入?yún)?shù)的個(gè)數(shù)
[ ! -f $1 ] : 要求用戶傳入的參數(shù)是一個(gè)文件,-f的用法見(jiàn)test命令,man test
income=$1:把用戶傳入的參數(shù)賦值給income變量,并在后面作為awk的參數(shù),即需要處理的文件
awk....:用文件中的第三列除以第二列,求出月均收入,考慮到精確性,保留了兩位有效數(shù)字。
sort -k 2 -n -r: 這里對(duì)結(jié)果的awk結(jié)果的第二列(-k 2),即月均收入進(jìn)行排序,按照數(shù)字排序(-n),并按照遞減的順序排序(-r)。

演示:
Quote:

$ ./gettopfamily.sh income
7 1696.33
9 1548.75
1 1496.67
4 1179.00
5 1144.50
10 1029.00
6 899.83
2 779.20
3 778.00
8 504.83



補(bǔ)充:之前的income數(shù)據(jù)是隨機(jī)產(chǎn)生的。在做一些實(shí)驗(yàn)時(shí),往往需要隨機(jī)產(chǎn)生一些數(shù)據(jù),在下一小節(jié),我們將詳細(xì)介紹它。這里是產(chǎn)生income數(shù)據(jù)的腳本:



Code:

[Ctrl+A Select All]



說(shuō)明:上述腳本中還用到seq命令產(chǎn)生從1到10的一列數(shù),這個(gè)命令的詳細(xì)用法在該篇最后一節(jié)也會(huì)進(jìn)一步介紹。

3. 隨機(jī)數(shù)

環(huán)境變量RANDOM產(chǎn)生0到32767的隨機(jī)數(shù),而awk的rand函數(shù)可以產(chǎn)生0到1之間的隨機(jī)數(shù)。

3.1 概要示例:打印一個(gè)隨機(jī)數(shù)

Quote:

$ echo $RANDOM
81
$ echo "" | awk '{srand(); printf("%f", rand());}'
0.237788



說(shuō)明:srand在無(wú)參數(shù)時(shí),采用當(dāng)前時(shí)間作為rand隨機(jī)數(shù)產(chǎn)生器的一個(gè)seed。

3.2 范例演示:隨機(jī)產(chǎn)生一個(gè)從0到255之間的數(shù)字

3.2.1 可以通過(guò)RANDOM變量的縮放和awk中rand的放大來(lái)實(shí)現(xiàn)。

Quote:

$ expr $RANDOM / 128
$ echo "" | awk '{srand(); printf("%d\n", rand()*255);}'



思考:如果要隨機(jī)產(chǎn)生某個(gè)IP段的IP地址,該如何做呢?

3.2.2 友善地獲取一個(gè)可用的IP地址

這個(gè)腳本我在蘭大開(kāi)源社區(qū)的討論區(qū)發(fā)過(guò),具體的分析過(guò)程見(jiàn)《貌似IP地址老被搶,寫(xiě)個(gè)腳本自動(dòng)換個(gè)可用的(非破壞性)

代碼:


Code:

[Ctrl+A Select All]



說(shuō)明:如果網(wǎng)關(guān)地址不是1,那么用ifconfig配置地址時(shí)不能配置為網(wǎng)關(guān)地址,否則你的IP地址將和網(wǎng)關(guān)一樣,導(dǎo)致整個(gè)網(wǎng)絡(luò)出現(xiàn)問(wèn)題。

4. 產(chǎn)生一序列數(shù)

其實(shí)我們通過(guò)一個(gè)循環(huán)就可以產(chǎn)生一序列數(shù),但是有相關(guān)的小工具為什么不用呢!seq就是這么一個(gè)小工具,它可以產(chǎn)生一序列數(shù),你可以指定數(shù)的遞增間隔,也可以指定相鄰兩個(gè)數(shù)之間的分割符。

4.1 概要示例:演示seq,打印一序列數(shù)

Quote:

$ seq 5
1
2
3
4
5
$ seq 1 5
1
2
3
4
5
$ seq 1 2 5
1
3
5
$ seq -s: 1 2 5
1:3:5
$ seq 1 2 14
1
3
5
7
9
11
13
$ seq -w 1 2 14
01
03
05
07
09
11
13
$ $ seq -s: -w 1 2 14
01:03:05:07:09:11:13



補(bǔ)充:在bash版本3中,在for循環(huán)的in后面,可以直接通過(guò){1..5}更簡(jiǎn)潔地產(chǎn)生自1到5的數(shù)字(注意,1和5之間只有兩個(gè)點(diǎn)),例如:
Quote:

$ for i in {1..5}; do echo -n "$i "; done
1 2 3 4 5

4.2 統(tǒng)計(jì)指定字符串(這里以單詞為例)的個(gè)數(shù)

這個(gè)靈感來(lái)自《高級(jí)Bash腳本編程指南》“混雜命令”seq的實(shí)例之“字母統(tǒng)計(jì)”和CU上一篇統(tǒng)計(jì)字母和數(shù)字個(gè)數(shù)的帖子。

4.2.1 首先,我們統(tǒng)計(jì)某個(gè)文件中所有單詞的個(gè)數(shù)。這里的單詞我定義為:由字母組成的單個(gè)或者多個(gè)字符序列。所以,可以這樣實(shí)現(xiàn)。

說(shuō)明:為了方便演示,這里采用我的上一篇轉(zhuǎn)載的日志happiness quotations里頭的內(nèi)容,請(qǐng)把內(nèi)容復(fù)制下來(lái)保存為text文件。

Quote:

//統(tǒng)計(jì)每個(gè)單詞出現(xiàn)的次數(shù)
$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c
//統(tǒng)計(jì)出出現(xiàn)頻率最高的前10個(gè)單詞
$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c | sort -n -k 1 -r | head -10
     45 is
     40 to
     32 of
     31 a
     28 and
     27 the
     25 happiness
     19 happy
     18 it
     18 in



說(shuō)明:
cat text: 顯示text文件里的內(nèi)容
sed -e "s/[^a-zA-Z]/\n/g": 把非字母的字符全部替換成空格,這樣整個(gè)文本只剩下字母字符
grep -v ^$:去掉空行
sort: 排序
uniq -c:統(tǒng)計(jì)相同行的個(gè)數(shù),即每個(gè)單詞的個(gè)數(shù)
sort -n -k 1 -r:按照第一列(-k 1)的數(shù)字(-n)逆序(-r)排序
head -10:取出前十行

4.2.2 接著我們統(tǒng)計(jì)指定單詞的個(gè)數(shù),即輸入需要統(tǒng)計(jì)的單詞,并返回每個(gè)單詞的個(gè)數(shù)。

可以考慮采取兩種辦法:
第一種:只統(tǒng)計(jì)那些需要統(tǒng)計(jì)的單詞
第二種:用上面的算法把所有單詞的個(gè)數(shù)都統(tǒng)計(jì)出來(lái),然后再返回那些需要統(tǒng)計(jì)的單詞給用戶

不過(guò),這兩種辦法都可以通過(guò)下面的結(jié)構(gòu)來(lái)實(shí)現(xiàn)。



Code:

[Ctrl+A Select All]



說(shuō)明:
if 條件部分:要求用戶輸入至少兩個(gè)參數(shù),第一個(gè)是需要統(tǒng)計(jì)單詞的文件名,第二之后的所有參數(shù)是需要統(tǒng)計(jì)的單詞。
FILE=$1: 獲取文件名,即腳本之后的第一個(gè)字符串。
((WORDS_NUM=$#-1)):獲取單詞個(gè)數(shù),即總的參數(shù)個(gè)數(shù)($#)減去那個(gè)文件名參數(shù)(1個(gè))
for 循環(huán)部分:首先通過(guò)seq產(chǎn)生需要統(tǒng)計(jì)的單詞個(gè)數(shù)序列,shift是shell內(nèi)置變量(請(qǐng)通過(guò)help shift獲取幫助),它把用戶從命令行中傳入的參數(shù)依次往后移動(dòng)位置,并把當(dāng)前參數(shù)作為第一個(gè)參數(shù)即$1,這樣通過(guò)$1就可以遍歷用戶所有輸入的單詞 (仔細(xì)一想,這里貌似有數(shù)組下標(biāo)的味道)。你可以考慮把shift之后的那句替換成echo $1測(cè)試shift的用法。

演示:
Quote:

$ chmod +x statistic_words.sh
$ ./statistic_words.sh text is Action happy
     45 is
      1 Action
     19 happy



采用第二種辦法,我們只需要修改shift之后的那句即可。


Code:

[Ctrl+A Select All]



演示:
Quote:

$ ./statistic_words.sh text is Action happy
     45 is
      1 Action
     19 happy



說(shuō)明:很明顯,采用第一種辦法效率要高很多,因?yàn)榈谝环N辦法提前找出了需要統(tǒng)計(jì)的單詞,然后再統(tǒng)計(jì),而后者則不然。實(shí)際上,如果使用grep的-E選項(xiàng),我們無(wú)須引入循環(huán),而用一條命令就可以搞定:

Quote:

$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | grep -E "^Action$|^is$" | uniq
-c
或者
$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | egrep  "^Action$|^is$" | uniq
-c
[/code]
所以,可見(jiàn)這些命令sed,grep,uniq,sort是多么有用,它們本身雖然只完成簡(jiǎn)單的功能,但是通過(guò)一定的組合,就可以實(shí)現(xiàn)你想要實(shí)現(xiàn)的功能啦。對(duì)了,統(tǒng)計(jì)單詞還有個(gè)非常有用的命令wc -w,需要用到的時(shí)候也可以用它。

補(bǔ)充:在《高級(jí)Bash腳本編程指南》一書(shū)中還提到j(luò)ot命令和factor命令,由于我機(jī)器上沒(méi)有,所以沒(méi)有測(cè)試,factor命令可以產(chǎn)生某個(gè)數(shù)的所有素?cái)?shù)。如:
[quote]
$ factor 100
100: 2 2 5 5



5. 總結(jié)

到這里,shell編程范例之?dāng)?shù)值計(jì)算就結(jié)束啦。該篇主要介紹了:

* shell編程中的整數(shù)運(yùn)算、浮點(diǎn)運(yùn)算、隨機(jī)數(shù)的產(chǎn)生、數(shù)列的產(chǎn)生
* shell的內(nèi)置命令、外部命令的區(qū)別,以及如何查看他們的類型和幫助,關(guān)于內(nèi)置命令和外部命令的比較,請(qǐng)參考:http://www.linuxpk.com/doc/abs/internal.html#READPIPEREF
* shell腳本的幾種執(zhí)行辦法
* 幾個(gè)常用的shell外部命令:sed,awk,grep,uniq,sort等
* 范例:數(shù)字遞增;求月均收入;自動(dòng)獲取IP地址;統(tǒng)計(jì)單詞個(gè)數(shù)
* 其他:相關(guān)的用法,比如命令列表,條件測(cè)試等,在上述范例中都已經(jīng)涉及,請(qǐng)認(rèn)真閱讀之

如果您有時(shí)間,請(qǐng)溫習(xí)之。

6. 參考資料和推薦資料

[1] 高級(jí)Bash腳本編程指南
http://www.linuxpk.com/doc/abs/
[2] shell十三問(wèn)
http://bbs.chinaunix.net/thread-218853-1-1.html
[3] shell基礎(chǔ)十二篇
http://bbs.chinaunix.net/thread-452942-1-1.html
[4] 在linux下學(xué)習(xí)和工作
http://oss.lzu.edu.cn/modules/newbb/viewtopic.php?topic_id=775&forum=6
[5] 在linux下更高效的工作
http://oss.lzu.edu.cn/modules/newbb/viewtopic.php?topic_id=1074&forum=6
[6] SED手冊(cè)
http://phi.sinica.edu.tw/aspac/reports/96/96005/
[7] AWK使用手冊(cè)
http://www.chinaunix.net/jh/7/16985.html
http://phi.sinica.edu.tw/aspac/reports/94/94011/
[8] 幾個(gè)shell討論區(qū)
蘭大開(kāi)源社區(qū): http://oss.lzu.edu.cn/modules/newbb/viewforum.php?forum=26
LinuxSir.org: http://www.linuxsir.org/bbs/forumdisplay.php?f=60
ChinaUnix.net: http://bbs.chinaunix.net/forum-24-1.html

如果合適,建議直接找對(duì)應(yīng)的英文原版閱讀!

后記:

[1] 大概花了3個(gè)多小時(shí)才寫(xiě)完,目前是23:33,該回宿舍睡覺(jué)啦,明天起來(lái)修改錯(cuò)別字和補(bǔ)充一些內(nèi)容,朋友們晚安!
[2] 10月31號(hào),修改部分措辭,增加一篇統(tǒng)計(jì)家庭月均收入的范例,添加總結(jié)和參考資料,并用附錄所有代碼。
[3] SHELL編程是一件非常有趣的事情,如果您想一想:上面計(jì)算家庭月均收入的例子,然后和用M$ Excel來(lái)做這個(gè)工作比較,你會(huì)發(fā)現(xiàn)前者是那么簡(jiǎn)單和省事,而且給您以運(yùn)用自如的感覺(jué)。



描述:shell_examples_calculate
附件: shell_examples_calculate.tar.gz (5 K)

再附一個(gè)簡(jiǎn)單范例(問(wèn)題見(jiàn)XBW linux&unix版)

問(wèn)題:有這么兩個(gè)文件,第一列是坐標(biāo)點(diǎn),第二列是對(duì)應(yīng)的值,要求把兩文件中相同坐標(biāo)處的值求和,結(jié)果格式和原文件一致。

分析:這個(gè)問(wèn)題如果用shell做,用awk最合適不過(guò),當(dāng)然,還用到sort進(jìn)行排序預(yù)處理。

$ cat A
0.000000 -393.339844
1.000000 -403.556091
2.000000 -408.335876
3.000000 -391.387726
4.000000 -406.563660
5.000000 -413.982544
$ cat B
0.000000 -20.100649
1.000000   -9.304893
2.000000   -7.830594
3.000000 -29.411428
4.000000   -9.393303
5.000000 -23.742157
$ sort A B | awk 'BEGIN{oldpoint=-1;}{ if(oldpoint==$1){ printf("%f %f\n", $1, $2+oldvalue); } oldpoint=$1; oldvalue=$2; }'
0.000000 -413.440493
1.000000 -412.860984
2.000000 -416.166470
3.000000 -420.799154
4.000000 -415.956963
5.000000 -437.724701
關(guān)于余弦值轉(zhuǎn)角度

Quote:

//用bc -l計(jì)算,可以獲得高精度
$ export cos=0.996293; echo "scale=100; a(sqrt(1-$cos^2)/$cos)*180/(a(1)*4)" |bc -l
4.934954755411383632719834036931840605159706398655243875372764917732\
5495504159766011527078286004072131
//用awk
$ echo 0.996293 | awk '{ printf("%-10s %-10s", $1, atan2(sqrt(1-$1^2),$1)*180/3.1415926535);}'



把一個(gè)文件中第2列的所有余弦值轉(zhuǎn)換為角度

Quote:

$ cat data
2000     1         0
2005     0.996293     4.93515
2010     0.999609     1.60303
2015     0.98501     9.9332
2020     0.999488     1.83398
2025     0.999409     1.9702
2030     0.99943     1.93381
2035     0.999267     2.19348
2040     0.99679     4.59235
$ awk '{ printf("%-10s%-10s%-10s", $1, $2, $3); system("echo \"scale=10; a(sqrt(1-"$2"^2)/"$2")*180/3.1415926535\" | bc -l ");}' data
2000     1       0       0
2005     0.996293 4.93515   4.9349547602
2010     0.999609 1.60303   1.6022865295
2015     0.98501   9.9332   9.9330460660
2020     0.999488 1.83398   1.8335432105
2025     0.999409 1.9702   1.9699389820
2030     0.99943   1.93381   1.9346200645
2035     0.999267 2.19348   2.1938966333
2040     0.99679   4.59235   4.5920476729
$ awk '{ printf("%-10s%-10s%-10s %f\n", $1, $2, $3, atan2(sqrt(1-$2^2), $2)*180/3.1415926535)}' data
2000     1       0       0.000000
2005     0.996293 4.93515   4.934955
2010     0.999609 1.60303   1.602286
2015     0.98501   9.9332   9.933046
2020     0.999488 1.83398   1.833543
2025     0.999409 1.9702   1.969939
2030     0.99943   1.93381   1.934620
2035     0.999267 2.19348   2.193897
2040     0.99679   4.59235   4.592048



詳細(xì)解答過(guò)程請(qǐng)參考:

http://bbs.lzu.edu.cn/wForum/disparticle.php?boardName=LinuxUnix&ID=28597&pos=2

感興趣的朋友看看這些范例:
1. 《Shell 編程實(shí)例集錦》
http://www.lupaworld.com/35714/viewspace_21170.html

另外,通過(guò)這篇可以深入學(xué)習(xí)一下AWK的實(shí)際應(yīng)用價(jià)值:
2. 巧用AWK處理二進(jìn)制數(shù)據(jù)文件
http://www.ibm.com/developerworks/cn/linux/shell/awk/binary/

關(guān)于不同類型的數(shù)值常量(如八進(jìn)制、16進(jìn)制的表示等)的表示,請(qǐng)參考 《高級(jí)Bash腳本編程指南》http://www.linuxpk.com/doc/abs/numerical-constants.html#NUMBERS

東西總是學(xué)不完,大伙繼續(xù),這里是幾個(gè)好去處,一天看上幾篇,保證受益不少:

[1] linuxsir.org Shell版精華
http://www.linuxsir.org/bbs/forum60--1-desc-goodnees.html
[2] chinaunix.net Shell版綜合水平測(cè)試
http://bbs.chinaunix.net/thread-476260-27-1.html
[3] linuxsir.org Shell技巧交流區(qū)
http://www.linuxsir.org/bbs/thread173263.html
[4] linuxsir.org Shell腳本欣賞區(qū)
http://www.linuxsir.org/bbs/showthread.php?threadid=29701

用bc計(jì)算器計(jì)算“Unix高級(jí)編程”第一章課后系統(tǒng)最后兩個(gè)題目的計(jì)算過(guò)程:

Quote:

// 1.5 若日歷存放在帶符號(hào)的32位整數(shù)中,那么到哪一年它將溢出?
$ echo "(2^31)/(360*24*60*60)+1970-1" | bc
2038
// 1.6 若進(jìn)程時(shí)間存放在帶符號(hào)的32位整數(shù)中,而且每秒為100滴答,那么經(jīng)過(guò)多少天后,該時(shí)間值將會(huì)溢出。
$ echo "2^31/(100*24*60*60)" | bc
248



以上兩道題需要明白兩個(gè)概念:
第一就是Unix時(shí)間存放的是從1970年1月1日到現(xiàn)在的秒數(shù),第二格式進(jìn)程時(shí)間存放的是進(jìn)程運(yùn)行到現(xiàn)在的滴答數(shù)。

如果有時(shí)間,這里頭的一些資料還是值得您仔細(xì)閱讀的:

"developerWorks 中國(guó) | Shell、Shell 腳本編寫(xiě)、命令行、相關(guān)工具及技巧"
http://www.ibm.com/developerworks/cn/linux/shell/index.html
需要補(bǔ)充的是,日期和時(shí)間是一個(gè)很好的隨機(jī)數(shù),它是一個(gè)在永恒變化的東西,所以,你無(wú)須擔(dān)心存在重復(fù),它很適合用于生成一些臨時(shí)文件。具體用法見(jiàn)man date,常用的有date +%s

剛從http://www.linuxpk.com/doc/abs/special-chars.html看到有趣的一點(diǎn),用(())加#還可以轉(zhuǎn)換進(jìn)制。
例如:

Quote:

# echo "$(( 8#11 ))"
9



即1*8^0 + 1*8^1 = 9

關(guān)于間接變量的引用問(wèn)題:

例如:

Quote:

$ a=b
$ b=c
$ echo $a
b
$ echo $b
c
$ eval echo \$$a
c
$ echo ${!a}
c



${!a}提供了一種非常方便的間接變量引用辦法,參考:
http://www.linuxpk.com/doc/abs/othertypesv.html

posted on 2008-03-14 15:48 隨意門 閱讀(5359) 評(píng)論(2)  編輯 收藏 引用

評(píng)論

# re: shell編程范例之?dāng)?shù)值運(yùn)算 2008-03-19 15:03 隨意門

# re: shell編程范例之?dāng)?shù)值運(yùn)算[未登錄](méi) 2009-01-09 10:05 Chris

樓主寫(xiě)得真的很好,像一份很好的教程。

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧洲免费视频| 亚洲欧美精品一区| 欧美激情国产日韩| 免费在线成人av| 欧美国产亚洲精品久久久8v| 欧美成人久久| 欧美视频一区二区三区四区| 国产精品久久久久一区二区三区| 国产精品视频九色porn| 狠狠色综合网站久久久久久久| 影音先锋成人资源站| 亚洲精品三级| 午夜日韩在线观看| 欧美成人午夜免费视在线看片| 亚洲高清免费| 亚洲国产一区在线观看| 亚洲精品综合精品自拍| 亚洲午夜视频在线观看| 久久久久久久久久看片| 欧美激情小视频| 国产麻豆精品theporn| 亚洲成色www8888| 亚洲午夜国产一区99re久久| 久久久久综合网| 99精品欧美一区二区蜜桃免费| 欧美一区二区大片| 欧美日本簧片| 在线观看视频亚洲| 亚洲欧美中文另类| 欧美电影免费观看网站| 一区二区三区欧美激情| 久久在线免费观看| 国产精品永久免费视频| 日韩视频在线观看一区二区| 久久久久久亚洲精品中文字幕| 亚洲激情婷婷| 久久久久久网| 国产免费一区二区三区香蕉精| 一区精品在线播放| 欧美一区午夜视频在线观看| 亚洲第一在线综合在线| 久久久久国产精品一区三寸| 欧美亚洲一区二区在线观看| 欧美va亚洲va国产综合| 国产精品久久久久久久午夜片| 欧美精品日韩一本| 欧美视频在线观看免费| 亚洲国产一区在线| 欧美中文在线视频| av成人免费| 欧美区国产区| 亚洲美女免费视频| 欧美国产精品中文字幕| 久久久久久久成人| 国产热re99久久6国产精品| 亚洲一区二区三区中文字幕在线| 最新国产精品拍自在线播放| 欧美成人午夜视频| 亚洲电影一级黄| 美国十次了思思久久精品导航| 亚洲视频在线观看三级| 欧美性开放视频| 亚洲欧美大片| 亚洲一区二区三区欧美| 欧美视频一区二区三区四区| 亚洲一区二区免费在线| 99精品99久久久久久宅男| 欧美色偷偷大香| 亚洲欧美精品伊人久久| 午夜激情亚洲| 经典三级久久| 亚洲国产日韩在线一区模特| 欧美三区美女| 久久精彩视频| 久久这里有精品视频| 亚洲欧洲另类国产综合| 亚洲人成在线影院| 国产精品久久久久久久久久免费看| 亚洲欧美日韩精品久久亚洲区 | 亚洲一区视频在线| 国产精品videossex久久发布| 亚洲一区二区三区国产| 在线亚洲激情| 亚洲自拍偷拍福利| 欲香欲色天天天综合和网| 久久久久久**毛片大全| 香蕉久久a毛片| 狠狠爱成人网| 欧美国产亚洲精品久久久8v| 欧美成人嫩草网站| 亚洲一区二区三区四区五区午夜| 亚洲欧美成人| 亚洲激情另类| 亚洲小说春色综合另类电影| 亚洲精品综合精品自拍| 亚洲社区在线观看| 亚洲一区二区影院| 红桃视频亚洲| 亚洲免费观看高清完整版在线观看熊| 国产精品视频观看| 亚洲国产mv| 国产精品午夜av在线| 欧美激情第六页| 国产三级精品在线不卡| 欧美成人性网| 国产欧美一级| 亚洲精品在线三区| 在线观看欧美日韩| 亚洲一区日韩| 一个色综合导航| 久久久久久亚洲综合影院红桃| 一区二区三区四区国产精品| 欧美在线看片a免费观看| 日韩视频免费观看| 久久福利毛片| 亚洲综合激情| 欧美精品三区| 欧美顶级少妇做爰| 亚洲欧美激情四射在线日| 日韩亚洲视频在线| 玖玖综合伊人| 欧美电影免费观看| 欧美成人一区二区三区在线观看| 欧美综合国产| 国产精品尤物福利片在线观看| 国产精品国产三级国产a| 亚洲午夜高清视频| 欧美日韩国产成人| 亚洲国产一区视频| 亚洲电影在线播放| 久久久久88色偷偷免费| 欧美一区二区三区电影在线观看| 欧美精选在线| 亚洲激情电影在线| 亚洲精品在线视频| 欧美精品日韩| 日韩一区二区免费看| 亚洲视频一区二区在线观看| 欧美福利精品| 亚洲精品欧美精品| 亚洲最新色图| 国产精品jvid在线观看蜜臀| 亚洲五月婷婷| 国产精品一区二区三区四区五区| 亚洲色无码播放| 亚洲少妇自拍| 国产美女精品人人做人人爽| 欧美在线一级va免费观看| 麻豆国产精品va在线观看不卡| 亚洲一区二区三区精品在线| 欧美日韩视频专区在线播放| 99精品热6080yy久久| 亚洲欧美在线高清| 韩国三级电影久久久久久| 一区视频在线| 欧美国产第一页| 99re国产精品| 国产精品久久久久久久久久免费| 亚洲在线不卡| 一本色道久久| 亚洲黄色av| 麻豆国产精品va在线观看不卡| 黄色精品一区| 欧美主播一区二区三区美女 久久精品人| 欧美福利小视频| 亚洲电影免费在线| 亚洲综合视频网| 欧美电影电视剧在线观看| 久久精品在这里| 欧美成人精品在线观看| 一区二区视频在线观看| 欧美大秀在线观看| 亚洲一区二区精品| 免费日韩成人| 亚洲欧美日韩国产一区二区| 国产视频自拍一区| 欧美www在线| 亚洲欧美在线另类| 亚洲成人资源| 午夜亚洲视频| 亚洲国产精品欧美一二99| 欧美日韩一区二区三区| 亚洲欧美日韩中文在线制服| 欧美韩日精品| 欧美一区二区视频在线| 亚洲精品综合精品自拍| 国产一区二区中文| 欧美日韩视频在线| 久久综合伊人77777尤物| 亚洲私人黄色宅男| 亚洲成人在线视频播放 | 亚洲亚洲精品三区日韩精品在线视频| 国产精品卡一卡二卡三| 久久视频在线看| 午夜精品免费视频| 日韩香蕉视频| 亚洲激情视频| 欧美激情综合| 欧美不卡在线视频| 久久大综合网|