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

Prayer

在一般中尋求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

利用 AWK 的數值計算功能提升工作效率

Posted on 2010-03-11 21:17 Prayer 閱讀(406) 評論(0)  編輯 收藏 引用 所屬分類: Shell
Awk 是一種優秀的文本樣式掃描和處理工具。本文側重介紹了 awk 在數值計算方面的運用,并通過幾個實際工作中的例子,闡述了如何利用 awk 的計算功能來提高我們的工作效率。

Awk 是一種優秀的文本樣式掃描和處理工具。 Awk 與 sed 和 grep 有些相似, 但功能比后者強不少。 awk 提供的功能包括樣式載入, 流控制,數學運算符,進程控制以及許多內置的變量和函數等。 借助于這些功能, 我們可以很方便地利用 awk 對各種文件 (如試驗產生的數據文件,數據庫文件等) 進行處理。 本文介紹了 awk 在數值計算方面的運用, 并通過幾個實際的例子, 闡述了如何利用 awk 的計算功能來提高我們的工作效率。

Awk 基本的運算符,數學函數以及簡單的運算實例

Awk 支持不少常見的運算符, 如 + (加),- (減), * (乘), / (除), ^ 或 ** (乘方), % (取模) 等等。 此外, awk 也提供了一些常用的數學函數, 比如 sin(x), cos(x), exp(x), log(x), sqrt(x), rand()。 使用這些運算符和函數可以直接進行一些簡單的運算:


清單 1. 用 awk 做簡單的數值計算

            echo | awk '{print 19+7}' ==> 26
            echo | awk '{print 19-7}' ==> 12
            echo | awk '{print 19*7}' ==> 133
            echo | awk '{print 19/7}' ==> 2.71429
            echo | awk '{print 19**7}' ==> 893871739
            echo | awk '{print 19%7}' ==> 5
            echo | awk '{print atan2(19, 7)}' ==> 1.21781
            

上面的計算也可以用一個腳本文件 calc.awk 來完成:


清單 2. 腳本文件 calc.awk

            {
            print $1 " + " $2 " = " $1 + $2
            print $1 " - " $2 " = " $1 - $2
            print $1 " x " $2 " = " $1 * $2
            print $1 " / " $2 " = " $1 / $2
            print $1 " ^ " $2 " = " $1 ** $2
            print $1 " mod " $2 " = " $1 % $2
            print " atan2( " $1 " , " $2 " ) " " = " atan2($1, $2)
            }
            

執行 awk -f calc.awk 19 7 可以得到和清單 1 中一樣的計算結果。 這里選項 -f 允許 awk 調用并執行程序文件 calc.awk; 最后的 197 是輸入, 分別對應于文件中的 $1$2





回頁首


復雜一些的數值計算

現在我們利用 awk 來完成一些稍微復雜的計算。 我們首先用 awk 來計算 Fibonacci 數列,相應的 awk 程序 Fib.awk 見清單3:


清單 3. 計算 Fibonacci 數列的程序文件
function fibo(n) {
            if(n<=1) return 1;
            return (fibo(n-2) + fibo(n-1));
            }
            BEGIN {
            n = (ARGV[1] < 1) ? 1 : ARGV[1];
            printf("%d\n", fibo(n));
            exit;
            }
            

計算時使用命令 awk -f Fib.awk n。 這里的輸入 n 是整數。 另外只要把上面程序中的函數fibo(n) 稍微改一下, 就可以用來進行階乘的運算, 修改后的代碼如下:


清單 4. 計算價乘的 awk 腳本
function factorial(n) {
            if(n<=1) return 1;
            return (n*factorial(n-1));
            }
            BEGIN {
            n = (ARGV[1] < 1) ? 1 : ARGV[1];
            printf("%d\n", factorial(n));
            exit;
            }
            

我們再來看一個求平方根的例子。 盡管 awk 提供了計算平方根的函數, 但我們也可以通過自己寫程序來實現, 相應的算法如清單 5 所示; 清單 6 則給出了一個具體的例子: 求數字 3.7 的平方根:

清單 5. 求平方根的算法

求平方根的算法
清單 6. 計算平方根的例子
BEGIN {
            a = 3.7;
            x = a;
            while((x**2-a)**2 > 1e-12) {
            x = (x + a/x)/2;
            }
            print x
            }
            





回頁首


實例1: 快速計算兩個文件之間的時間差

如果僅僅從事單純的數值計算, 恐怕 awk 不是我們最好的選擇, 畢竟 awk 是為了方便文本處理而設計的。 不過如果數值計算和文本有密切關系的話, 比方說計算之前要先處理文本中的數據 (如查找,提取數據), 這時 awk 的優勢就會充分顯示出來。 而這樣的情況在工作中往往是經常碰到的。 我們來看一個實際的例子。 假定我們要比較某些運行在 Linux 集群上的并行程序的效率, 一個可行的方法是估算這些程序運行所需的時間。 這些程序運行的時間通常比較長, 可以從 10 幾個小時到一個多星期。 注意到程序在運行中會不斷地生成數據文件, 而 Linux 系統會紀錄下每個數據文件被創建 (如果以前不存在) 或修改(如果以前存在) 的時間, 這樣就可以通過計算兩個文件的時間差來估計并行程序的效率。 我們知道 Linux 提供的 stat 命令可以用來獲取某個文件的各種屬性, 比如對數據文件 simu_space_1.dat 使用命令 stat simu_space_1.dat 會有如下的輸出:


清單 7. 命令 stat simu_space_1.dat 的輸出
File:  "simu_space_1.dat"
            Size: 237928    	Blocks: 480        IO Block: 4096   regular Datei
            Device: 801h/2049d	Inode: 2768915     Links: 1
            Access: (0644/-rw-r--r--)  Uid: ( 1000/     nst)   Gid: ( 1000/     nst)
            Access: 2008-11-14 10:56:05.000000000 +0100
            Modify: 2008-11-13 23:26:44.000000000 +0100
            Change: 2008-11-13 23:26:44.000000000 +0100
            

以上輸出包含了關鍵字 ’Modify’ 的一行中紀錄下了文件被修改的時間。 所以原則上說只要對兩個文件分別使用 stat 命令, 得到它們的修改時間, 就可以計算出它們之間的時間差。 如果計算的次數很少的話, 這個工作當然可以手工完成。 不過要頻繁計算的話就很費時間了, 而且出錯的幾率也會變大。 這種情況下我們可以求助 awk, 讓它來自動完成這個計算工作, 為此我們創建了下面的腳本 time_df.awk:


清單 8. 計算時間差的 awk 程序
BEGIN {
            n = 0;
            d1 = 0;
            s1 = 0;
            FS = ":|-| *";
            }
            {
            for(i=1; i<=NF; i++)
            {
            if($i~/Modify/)
            {
            n = n + 1;
            d = $(i+4);
            h = $(i+5);
            m = $(i+6);
            s = $(i+7);
            d1 = d1 + ((-1)**n)*d*24*3600;
            s1 = s1 + ((-1)**n)*(3600*h + 60*m + s);
            }
            }
            }
            END {
            s1 = s1 + d1;
            D = int(s1/(24*3600));
            H = int((s1 - D*24*3600)/3600);
            M = int((s1-D*24*3600-H*3600)/60);
            S = s1 % 60;
            printf("The total time required %d days, %d hours,   \
            %d minutes and %d seconds\n", D, H, M, S) ;
            }
            

上面的代碼是基于如下的考慮: 首先使用 awk 找到包含 ’Modify’ 關鍵字的那一行, 然后把其中有關日期和時間的數據提取出來。 由于直接對日期和時間做減法不是很方便, 所以先把日期和時間轉化為一個以秒為單位的數字 (從每個月的第一天0時0分0秒算起)。 容易理解, 由兩個數字相減得到的時間差也是以秒為單位的。 為了能直觀顯示, 輸出時再把這個時間差表達為天, 小時, 分鐘和秒。 要計算兩個文件 simu_space_1.dat 和 simu_space_100.dat 之間的時間差,可以用下面的命令:


清單 9. 計算文件時間差的命令
stat simu_space_1.dat simu_space_100.dat | awk -f time_df.awk
            

先生成的文件 simu_space_1.dat (也就是時間較早一些的) 放在前面,后生成的文件simu_space_100.dat 放在后面。 如果要算另外兩個文件之間的時間差, 只要換一下文件名就可以了。 借助于上面的 awk 代碼我們可以快速且精確地得到任意兩個數據文件的時間間隔。 需要指出的是, 上面的程序沒有考慮跨月度這種情況。 也就是說, 如果第一個數據文件是在某個月的月末生成, 而第二個文件是在下個月的月初生成, 這時就不能用它來計算, 因為得到的時間是沒有意義的負數。





回頁首


實例2: 驗證通量:從多個文件中提取數據并計算

這個例子是通過計算不同位置處的流體的通量來驗證它們是否相同。 這里的通量可視為某個截面上通過的顆粒濃度, 流體的速度和截面面積的乘積。 現在的問題是濃度, 速度等參數分布在不同的數據文件中, 而這些文件是字符和數據共存的, 比如包含濃度的文件 simu_space_1.dat 有如下的格式:

清單 10. 數據文件 simu_space_1.dat 的格式

{0.436737, 0.429223, 3.000000, 1.000000, 43300806482080792.000000, 243231808.137785},

{1.296425, 0.429223, 3.000000, 1.000000, 107468809895964656.000000, 584622938.047805},

{2.128973, 0.429223, 3.000000, 1.000000, 102324821165926400.000000, 539067822.351442},

......

{19.358569, 4.875000, 3.000000, 1.000000, 257544788738191712.000000, 1460324590.999991},

{19.620925, 4.875000, 3.000000, 1.000000, 266676357086157504.000000, 1464352706.940682},

{19.875000, 4.875000, 3.000000, 1.000000, 260249342336872224.000000, 1383971975.659338},

第一步當然是從上面的文件中把某個位置上的濃度數據 (每一行左起第五個數字) 提取出來。 下面的 awk 代碼是把位置 x = 0.429223 處的濃度提取出來, 并保存到一個臨時文件 number.txt 中:


清單 11. 提取指定位置處的數據并保存
awk  -F'{|,\t|},' '{for(i=1; i<NF; i++) {if($i~/0.429223/) print $(i+3)}}'  \
            simu_space_1.dat > number.txt
            

現在文件 number.txt 中有了一列濃度數據。 接著我們從其他文件中提取在同一位置處的速度和面積的數據, 然后把它們分別保存到臨時文件 velocity.txt 和 area.txt 中。 然后把三個臨時文件中的數據合并到另一個文件 flux.txt 中以方便 awk 的計算。 這個合并操作可以用工具 paste 來輕松完成, 代碼如清單 12:


清單 12. 合并不同文件中的數據到一個文件
paste number.txt velocity.txt area.txt > flux.txt
            

現在 flux.txt 中包含了三列數據, 分別是濃度,速度和面積。 按照前面介紹的通量計算方法, 文件 flux.txt 中每一行的三個數據要首先相乘, 然后再把所有的乘積加起來就可以得到通過那個截面的通量了, 具體的代碼見清單13:


清單 13. 計算通量的 awk 代碼
awk '{x=x+($1*$2*$3)} END {print x}' flux.txt
            

上面的代碼使用了一個變量 x, 第一次執行時, x 被賦予文件 flux.txt 中第一行三個數據的乘積。 第二次執行時, 它保留了第一次計算的值并加上第二行三個數據的乘積, 以此類推, 直到達到累計的總合。 END 的作用是只顯示最后的結果, 而不顯示中間的累加結果。 我們可以做一個比較, 以前我們是利用其他的軟件 (比如 Excel 或者 OpenOffice Calc) 來計算通量的。 這必然要涉及到導入數據, 選擇相應的計算函數等一系列的操作, 而用 awk 只要一行代碼! 如果再考慮到計算之前從不同文件中提取數據的工作也是由 awk 完成的 (其實也就是幾行代碼), 所以對本例而言使用 awk 節約了可觀的時間。





回頁首


總結

不應忽視 awk 的數值計算功能, 它能完成從簡單到比較復雜的數值運算。 尤其當計算過程中涉及到數據文件的處理, 這時使用 awk 往往會很方便。 因為 awk 本身有很強的文本處理功能, 它可以輕松地把數據從文本中分離出來, 然后再進行相應的計算。 本文的實例說明了如果能靈活地使用 awk 的這些功能, 有可能會顯著地提升我們的工作效率。



參考資料



關于作者

 

在德國 Duisburg-Essen 大學, NST 工作. 對 Linux 和 open source software 很感興趣.

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            宅男精品视频| 国产精品视频内| 国产精品日韩精品欧美精品| 亚洲人成毛片在线播放女女| 亚洲欧洲视频在线| 国内久久精品视频| 国产精品人成在线观看免费| 欧美国产第一页| 浪潮色综合久久天堂| 欧美在线视频a| 一区二区三区三区在线| 亚洲日本一区二区三区| 欧美激情在线狂野欧美精品| 久久精品免费看| 久久精品视频在线| 欧美一区午夜视频在线观看| 亚洲午夜电影网| 亚洲午夜电影在线观看| 久久不射网站| 久久乐国产精品| 亚洲欧美日韩成人高清在线一区| 一区视频在线| 亚洲女人小视频在线观看| 亚洲黄网站在线观看| 日韩亚洲欧美成人| 一本久道久久综合狠狠爱| 欧美黑人在线观看| 狼人社综合社区| 日韩视频欧美视频| 欧美一级日韩一级| 亚洲国产国产亚洲一二三| 亚洲精品之草原avav久久| 一区二区免费看| 久久久精品性| 国产麻豆成人精品| 日韩亚洲在线| 久久综合网hezyo| 亚洲欧美日韩一区二区三区在线观看| 久久久久久久999| 国产精品一二三视频| 中文网丁香综合网| 欧美激情视频给我| 免费久久精品视频| 欧美午夜不卡视频| 一区二区三区色| 午夜久久久久久| 亚洲国产日韩在线一区模特| 久久精品国产99| 国产色产综合产在线视频| 亚洲一区中文字幕在线观看| 亚洲精品123区| 欧美日韩精品| 亚洲精品日韩激情在线电影| 99re8这里有精品热视频免费| 欧美电影免费网站| 亚洲精品三级| 野花国产精品入口| 国产深夜精品福利| 欧美成年网站| 欧美日韩二区三区| 欧美日韩一区二区免费在线观看| 国产日韩视频一区二区三区| 亚洲自啪免费| 亚洲精品视频一区二区三区| 蜜桃av一区二区| 99热在这里有精品免费| 欧美黄色免费| 亚洲激情电影中文字幕| 亚洲一级在线观看| 一区二区在线不卡| 亚洲免费观看| 亚洲激情欧美| 一区二区三区黄色| 亚洲国产第一| 亚洲淫片在线视频| 99re这里只有精品6| 亚洲综合国产| 一区二区三区免费在线观看| 久久久久国产精品一区三寸| 中文亚洲视频在线| 欧美人与禽猛交乱配视频| 久久精品国产一区二区电影| 欧美日韩一区二区在线播放| 久久乐国产精品| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲欧美日韩一区二区三区在线| 欧美一区二区三区在线| 久久另类ts人妖一区二区| 国产亚洲欧洲997久久综合| 亚洲一区在线观看视频| 欧美日韩一本到| 亚洲色图制服丝袜| 久久国产99| 亚洲国语精品自产拍在线观看| 欧美黄色aa电影| aa亚洲婷婷| 亚洲一区二区欧美日韩| 欧美精品综合| 亚洲香蕉视频| 欧美黑人在线观看| 亚洲欧洲一区二区三区在线观看| 老司机精品福利视频| 欧美不卡高清| 99视频精品全国免费| 国产精品久久久久天堂| 欧美在线播放| 亚洲看片网站| 久久久午夜视频| 日韩午夜免费| 在线观看精品一区| 国产精品国产三级国产a| 久久激情五月婷婷| 午夜精品久久久久久99热软件| 欧美大片免费看| 亚洲免费伊人电影在线观看av| 国内自拍视频一区二区三区| 欧美国产91| 免费精品99久久国产综合精品| 亚洲无吗在线| 亚洲男人的天堂在线| 亚洲一区二区三区免费视频 | 欧美日韩国产综合视频在线观看中文| 午夜日韩av| 欧美一区二区三区的| 一区二区三区高清视频在线观看| 噜噜噜在线观看免费视频日韩| 亚洲欧美日韩网| 日韩亚洲综合在线| 免费欧美高清视频| 欧美大尺度在线观看| 免费观看日韩| 欧美日韩大片| 欧美成人中文字幕| 日韩亚洲视频在线| 亚洲日韩视频| 亚洲私人影院在线观看| 欧美激情二区三区| 久久综合色一综合色88| 免费av成人在线| 欧美久久久久| 国产精品素人视频| 国产无遮挡一区二区三区毛片日本| 国产精品成人观看视频国产奇米| 欧美激情中文字幕乱码免费| 欧美日韩一区二区三区四区五区| 欧美黄色片免费观看| 欧美精品一区在线| 欧美三级网页| 欧美亚洲成人精品| 狠狠色伊人亚洲综合成人| 99伊人成综合| 亚洲系列中文字幕| 性色一区二区三区| 亚洲国产精品99久久久久久久久| 亚洲精品网址在线观看| 先锋影音网一区二区| 欧美成人国产| 国产一区二区三区丝袜| 亚洲人妖在线| 欧美激情1区| 日韩一级大片在线| 欧美精品激情在线观看| 国产小视频国产精品| 亚洲大片免费看| 久久久www| 亚洲国产成人高清精品| 亚洲人成免费| 亚洲调教视频在线观看| 看欧美日韩国产| 亚洲精品一区二区三区蜜桃久| 国产精品影院在线观看| 一区二区久久久久| 91久久精品网| 欧美激情女人20p| 亚洲激情成人网| 欧美黄色精品| 欧美成人激情在线| 在线精品视频免费观看| 浪潮色综合久久天堂| 久久久精品性| 国产日本精品| 老司机久久99久久精品播放免费 | 午夜精品国产精品大乳美女| 亚洲在线观看免费视频| 亚洲国产精品久久人人爱蜜臀 | 最新中文字幕亚洲| 国产精品日韩欧美大师| 亚洲图片在线| 久久久www成人免费毛片麻豆| 国产日韩成人精品| 亚洲欧洲午夜| 国产精品视频自拍| 亚洲黄色免费| 亚洲精品视频在线| 久久激情一区| 韩国欧美国产1区| 亚洲一区二区三区色| 久久精品综合一区| 久久久久久久久蜜桃| 国产精品豆花视频|