日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

20分钟 Awk 入门

發布時間:2024/3/24 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 20分钟 Awk 入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

20分鐘 Awk 入門

什么是Awk

Awk是一種小巧的編程語言及命令行工具。(其名稱得自于它的創始人Alfred Aho、Peter Weinberger 和 Brian Kernighan姓氏的首個字母)。它非常適合服務器上的日志處理,主要是因為Awk可以對文件進行操作,通常以可讀文本構建行。

我說它適用于服務器是因為日志文件,轉儲文件(dump files),或者任意文本格式的服務器終止轉儲到磁盤都會變得很大,并且在每個服務器你都會擁有大量的這類文件。如果你經歷過這樣的情境——在沒有像Splunk或者其他等價的工具情況下不得不在50個不同的服務器里分析幾G的文件,你會覺得去獲取和下載所有的這些文件并分析他們是一件很糟糕的事。

我親身經歷過這種情境。當一些Erlang節點將要死掉并留下一個700MB到4GB的崩潰轉儲文件(crash dump)時,或者當我需要在一個小的個人服務器(叫做VPS)上快速瀏覽日志,查找一個常規模式時。

在任何情況下,Awk都不僅僅只是用來查找數據的(否則,grep或者ack已經足夠使用了)——它同樣使你能夠處理數據并轉換數據。

代碼結構

Awk腳本的代碼結構很簡單,就是一系列的模式(pattern)和行為(action):

  • # comment
  • Pattern1 { ACTIONS; }
  • # comment
  • Pattern2 { ACTIONS; }
  • # comment
  • Pattern3 { ACTIONS; }
  • # comment
  • Pattern4 { ACTIONS; }
  • 掃描文檔的每一行時都必須與每一個模式進行匹配比較,而且一次只匹配一個模式。那么,如果我給出一個包含以下內容的文件:

  • this is line 1
  • this is line 2
  • this is line 1 這行就會與Pattern1進行匹配。如果匹配成功,就會執行ACTIONS。然后this is line 1 會和Pattern2進行匹配。如果匹配失敗,它就會跳到Pattern3進行匹配,以此類推。

    一旦所有的模式都匹配過了,this is line 2 就會以同樣的步驟進行匹配。其他的行也一樣,直到讀取完整個文件。

    簡而言之,這就是Awk的運行模式

    數據類型

    Awk僅有兩個主要的數據類型:字符串和數字。即便如此,Awk的字符串和數字還可以相互轉換。字符串能夠被解釋為數字并把它的值轉換為數字值。如果字符串不包含數字,它就被轉換為0.

    它們都可以在你代碼里的ACTIONS部分使用 = 操作符給變量賦值。我們可以在任意時刻、任意地方聲明和使用變量,也可以使用未初始化的變量,此時他們的默認值是空字符串:“”。

    最后,Awk有數組類型,并且它們是動態的一維關聯數組。它們的語法是這樣的:var[key] = value 。Awk可以模擬多維數組,但無論怎樣,這是一個大的技巧(big hack)。

    模式

    可以使用的模式分為三大類:正則表達式、布爾表達式和特殊模式。

    正則表達式和布爾表達式

    你使用的Awk正則表達式比較輕量。它們不是Awk下的PCRE(但是gawk可以支持該庫——這依賴于具體的實現!請使用 awk

    –version查看),然而,對于大部分的使用需求已經足夠了:

  • /admin/ { ... } # any line that contains 'admin'
  • /^admin/ { ... } # lines that begin with 'admin'
  • /admin$/ { ... } # lines that end with 'admin'
  • /^[0-9.]+ / { ... } # lines beginning with series of numbers and periods
  • /(POST|PUT|DELETE)/ # lines that contain specific HTTP verbs
  • 注意,模式不能捕獲特定的組(groups)使它們在代碼的ACTIONS部分執行。模式是專門匹配內容的。

    布爾表達式與PHP或者Javascript中的布爾表達式類似。特別的是,在awk中可以使用&&(“與”)、||(“或”)、!(“非”)操作符。你幾乎可以在所有類C語言中找到它們的蹤跡。它們可以對常規數據進行操作。

    與PHP和Javascript更相似的特性是比較操作符,==,它會進行模糊匹配(fuzzy matching)。因此“23”字符串等于23,”23″ == 23 表達式返回true。!= 操作符同樣在awk里使用,并且別忘了其他常見的操作符:>,<,>=,和<=。

    你同樣可以混合使用它們:布爾表達式可以和常規表達式一起使用。 /admin/ || debug == true 這種用法是合法的,并且在遇到包含“admin”單詞的行或者debug變量等于true時該表達式就會匹配成功。

    注意,如果你有一個特定的字符串或者變量要與正則表達式進行匹配,~ 和!~ 就是你想要的操作符。 這樣使用它們:string ~ /regex/ 和 string !~ /regex/。

    同樣要注意的是,所有的模式都只是可選的。一個包含以下內容的Awk腳本:

    { ACTIONS }

    對輸入的每一行都將會簡單地執行ACTIONS。

    特殊的模式

    在Awk里有一些特殊的模式,但不是很多。

    第一個是BEGIN,它僅在所有的行都輸入到文件之前進行匹配。這是你可以初始化你的腳本變量和所有種類的狀態的主要地方。

    另外一個就是END。就像你可能已經猜到的,它會在所有的輸入都被處理完后進行匹配。這使你可以在退出前進行清除工作和一些最后的輸出。

    最后一類模式,要把它進行歸類有點困難。它處于變量和特殊值之間,我們通常稱它們為域(Field)。而且名副其實。

    使用直觀的例子能更好地解釋域:

  • # According to the following line
  • #
  • # $1 $2 $3
  • # 00:34:23 GET /foo/bar.html
  • # _____________ _____________/
  • # $0
  • ?
  • # Hack attempt?
  • /admin.html$/ && $2 == "DELETE" {
  • print "Hacker Alert!";
  • }
  • 域(默認地)由空格分隔。$0 域代表了一整行的字符串。 $1 域是第一塊字符串(在任何空格之前), $2 域是后一塊,以此類推。

    一個有趣的事實(并且是在大多是情況下我們要避免的事情),你可以通過給相應的域賦值來修改相應的行。例如,如果你在一個塊里執行 $0 = “HAHA THE LINE IS GONE”,那么現在下一個模式將會對修改后的行進行操作而不是操作原始的行。其他的域變量都類似。

    行為

    這里有一堆可用的行為(possible actions),但是最常用和最有用的行為(以我的經驗來說)是:

  • { print $0; } # prints $0. In this case, equivalent to 'print' alone
  • { exit; } # ends the program
  • { next; } # skips to the next line of input
  • { a=$1; b=$0 } # variable assignment
  • { c[$1] = $2 } # variable assignment (array)
  • ?
  • { if (BOOLEAN) { ACTION }
  • else if (BOOLEAN) { ACTION }
  • else { ACTION }
  • }
  • { for (i=1; i<x; i++) { ACTION } }
  • { for (item in c) { ACTION } }
  • 這些內容將會成為你的Awk工具箱的主要工具,在你處理日志之類的文件時你可以隨意地使用它們。

    Awk里的變量都是全局變量。無論你在給定的塊里定義什么變量,它對其他的塊都是可見的,甚至是對每一行都是可見的。這嚴重限制了你的Awk腳本大小,不然他們會造成不可維護的可怕結果。請編寫盡可能小的腳本。

    函數

    可以使用下面的語法來調用函數:

  • { somecall($2) }
  • 這里有一些有限的內置函數可以使用,所以我可以給出這些函數的通用文檔(regular documentation)。

    用戶定義的函數同樣很簡單:

  • # function arguments are call-by-value
  • function name(parameter-list) {
  • ACTIONS; # same actions as usual
  • }
  • ?
  • # return is a valid keyword
  • function add1(val) {
  • return val+1;
  • }
  • 特殊變量

    除了常規變量(全局的,可以在任意地方使用),這里還有一系列特殊的變量,它們的的作用有點像配置條目(configuration entries):

  • BEGIN { # Can be modified by the user
  • FS = ","; # Field Separator
  • RS = "n"; # Record Separator (lines)
  • OFS = " "; # Output Field Separator
  • ORS = "n"; # Output Record Separator (lines)
  • }
  • { # Can't be modified by the user
  • NF # Number of Fields in the current Record (line)
  • NR # Number of Records seen so far
  • ARGV / ARGC # Script Arguments
  • }
  • 我把可修改的變量放在BEGIN里,因為我更喜歡在那重寫它們。但是這些變量的重寫可以放在腳本的任意地方然后在后面的行里生效。

    示例

    以上的就是Awk語言的核心內容。我這里沒有大量的例子,因為我趨向于使用Awk來完成快速的一次性任務。

    不過我依然有一些隨身攜帶的腳本文件,用來處理一些事情和測試。我最喜歡的一個腳本是用來處理Erlang的崩潰轉儲文件,形如下面的:

  • =erl_crash_dump:0.3
  • Tue Nov 18 02:52:44 2014
  • Slogan: init terminating in do_boot ()
  • System version: Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
  • Compiled: Fri Sep 19 03:23:19 2014
  • Taints:
  • Atoms: 12167
  • =memory
  • total: 19012936
  • processes: 4327912
  • processes_used: 4319928
  • system: 14685024
  • atom: 339441
  • atom_used: 331087
  • binary: 1367680
  • code: 8384804
  • ets: 382552
  • =hash_table:atom_tab
  • size: 9643
  • used: 6949
  • ...
  • =allocator:instr
  • option m: false
  • option s: false
  • option t: false
  • =proc:<0.0.0>
  • State: Running
  • Name: init
  • Spawned as: otp_ring0:start/2
  • Run queue: 0
  • Spawned by: []
  • Started: Tue Nov 18 02:52:35 2014
  • Message queue length: 0
  • Number of heap fragments: 0
  • Heap fragment data: 0
  • Link list: [<0.3.0>, <0.7.0>, <0.6.0>]
  • Reductions: 29265
  • Stack+heap: 1598
  • OldHeap: 610
  • Heap unused: 656
  • OldHeap unused: 468
  • Memory: 18584
  • Program counter: 0x00007f42f9566200 (init:boot_loop/2 + 64)
  • CP: 0x0000000000000000 (invalid)
  • =proc:<0.3.0>
  • State: Waiting
  • ...
  • =port:#Port<0.0>
  • Slot: 0
  • Connected: <0.3.0>
  • Links: <0.3.0>
  • Port controls linked-in driver: efile
  • =port:#Port<0.14>
  • Slot: 112
  • Connected: <0.3.0>
  • ...
  • 產生下面的結果:

  • $ awk -f queue_fun.awk $PATH_TO_DUMP
  • MESSAGE QUEUE LENGTH: CURRENT FUNCTION
  • ======================================
  • 10641: io:wait_io_mon_reply/2
  • 12646: io:wait_io_mon_reply/2
  • 32991: io:wait_io_mon_reply/2
  • 2183837: io:wait_io_mon_reply/2
  • 730790: io:wait_io_mon_reply/2
  • 80194: io:wait_io_mon_reply/2
  • ...
  • 這是在Erlang進程里運行的函數列表,它們導致了mailboxe變得很龐大。腳本在這:

  • # Parse Erlang Crash Dumps and correlate mailbox size to the currently running
  • # function.
  • #
  • # Once in the procs section of the dump, all processes are displayed with
  • # =proc:<0.M.N> followed by a list of their attributes, which include the
  • # message queue length and the program counter (what code is currently
  • # executing).
  • #
  • # Run as:
  • #
  • # $ awk -v threshold=$THRESHOLD -f queue_fun.awk $CRASHDUMP
  • #
  • # Where $THRESHOLD is the smallest mailbox you want inspects. Default value
  • # is 1000.
  • BEGIN {
  • if (threshold == "") {
  • threshold = 1000 # default mailbox size
  • }
  • procs = 0 # are we in the =procs entries?
  • print "MESSAGE QUEUE LENGTH: CURRENT FUNCTION"
  • print "======================================"
  • }
  • ?
  • # Only bother with the =proc: entries. Anything else is useless.
  • procs == 0 && /^=proc/ { procs = 1 } # entering the =procs entries
  • procs == 1 && /^=/ && !/^=proc/ { exit 0 } # we're done
  • ?
  • # Message queue length: 1210
  • # 1 2 3 4
  • /^Message queue length: / && $4 >= threshold { flag=1; ct=$4 }
  • /^Message queue length: / && $4 < threshold { flag=0 }
  • ?
  • # Program counter: 0x00007f5fb8cb2238 (io:wait_io_mon_reply/2 + 56)
  • # 1 2 3 4 5 6
  • flag == 1 && /^Program counter: / { print ct ":", substr($4,2) }
  • 你跟上思路沒?如果跟上了,你已經了解了Awk。恭喜!

    原文發布時間:2015-02-09

    本文來自云棲合作伙伴“linux中國”

    總結

    以上是生活随笔為你收集整理的20分钟 Awk 入门的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。