鍍金池/ 教程/ Linux/ shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)四十一天----列出文件 ls 和 od 命令
shell 學(xué)習(xí)小結(jié)
shell 學(xué)習(xí)第二十八天----case 語句
shell 學(xué)習(xí)四十四天----尋找文件
shell 學(xué)習(xí)三十五天----波浪號(hào)展開與通配符
shell 學(xué)習(xí)三十八天----執(zhí)行順序和 eval
shell 學(xué)習(xí)四十八天----文件校驗(yàn)和匹配
shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)第十一天----sed 正則的精確控制
shell 學(xué)習(xí)第十七天----awk 命令
shell 學(xué)習(xí)三十九天----內(nèi)建命令
shell 學(xué)習(xí)四十五天----xargs
shell 學(xué)習(xí)三十七天----引用
shell 學(xué)習(xí)第十六天----join 練習(xí)
shell 學(xué)習(xí)第二十四天----提取開頭或結(jié)尾數(shù)行
shell 學(xué)習(xí)第九天----分組
shell 學(xué)習(xí)第五天----基本的 I/O 重定向
shell 學(xué)習(xí)第十五天----使用 cut 選定字段
shell 學(xué)習(xí)四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學(xué)習(xí)第八天----擴(kuò)展正則表達(dá)式 (ERE)
shell 學(xué)習(xí)第十九天----文本塊排序
shell 學(xué)習(xí)第二十一天----重新格式化段落
shell 學(xué)習(xí)三十六天----命令替換
shell 學(xué)習(xí)第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學(xué)習(xí)四十二天----使用 touch 更新文件時(shí)間
shell 學(xué)習(xí)五十一天----top 命令查看進(jìn)程列表
shell 學(xué)習(xí)第一天
shell 學(xué)習(xí)五十四天----進(jìn)程系統(tǒng)調(diào)用的追蹤 strace
shell 學(xué)習(xí)五十天----查看進(jìn)程 ps 命令
shell 學(xué)習(xí)第二十七天----退出狀態(tài)和 if 語句
shell 學(xué)習(xí)第二十三天----打印
shell 學(xué)習(xí)三十三天----關(guān)于重定向
shell 學(xué)習(xí)四十九天----進(jìn)程建立
shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)五十五天----進(jìn)程記賬
shell 學(xué)習(xí)總結(jié)一
shell 學(xué)習(xí)第二十六天----變量與算數(shù)
shell 學(xué)習(xí)第二十二天----計(jì)算行數(shù), 字?jǐn)?shù)以及字符數(shù)
shell 學(xué)習(xí)五十八天----/proc 文件系統(tǒng)
shell 學(xué)習(xí)第二十五天----神器的管道符
shell 學(xué)習(xí)第三十二天----read 讀取一行
sheel 學(xué)習(xí)第三天
shell 學(xué)習(xí)----小結(jié)
shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)第三十一天----函數(shù)問題
shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十三天----臨時(shí)性文件的建立與使用
shell 學(xué)習(xí)四十七天----文件比較 cmp,diff,patch
shell 學(xué)習(xí)三十四天----printf 詳解
shell 學(xué)習(xí)五十七天 ----linux 任務(wù)管理,針對上一講的總結(jié)和擴(kuò)展
shell 學(xué)習(xí)第六天----小結(jié)
shell 學(xué)習(xí)第十三天----sed 案例分析
shell 學(xué)習(xí)第七天----基礎(chǔ)正則表達(dá)式 (BRE)
shell 學(xué)習(xí)第十二天----行與字符串
shell 學(xué)習(xí)小結(jié)四
shell 學(xué)習(xí)第二十九天----循環(huán)
shell 學(xué)習(xí)五十二天----刪除進(jìn)程 kill 命令
shell 學(xué)習(xí)五十六天----延遲進(jìn)程調(diào)度
shell 學(xué)習(xí)第四天----華麗的 printf 輸出
shell 學(xué)習(xí)第十五天----join 連接字段
shell 學(xué)習(xí)完結(jié)篇----希望你能看到
shell 學(xué)習(xí)第二天
shell 學(xué)習(xí)五十三天----捕獲信號(hào) trap

shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)

awk 的驚人表現(xiàn)

awk 可以勝任幾乎所有的文本處理工作。

awk調(diào)用

調(diào)用 awk:

  • 方式一:命令行方式 awk [-F field-separator] 'commands' input-file(s) [ -F 域分隔符 ] 是可選的,因?yàn)?awk 使用空格作為缺省的域分隔符,因此如果要瀏覽域間有空格的文本,不必指定這個(gè)選項(xiàng),如果要瀏覽例如 passwd 文件。此文件名域以冒號(hào)作為分隔符,則必須指明 -F 選項(xiàng),如:awk -F 'commands' input-file

  • 方式二:將所有 awk 命令插入一個(gè)文件,并使阿瓦庫程序可執(zhí)行,然后用 awk 命令解釋器作為腳本的首行,以便通過鍵入腳本名成功來調(diào)用它。

  • 方式三:將所有的 awk 命令插入一個(gè)單純文件,然后調(diào)用:awk -f awk-script-file input-file(s)
    • -f 選項(xiàng)指明在文件 awk_script_file 中的 awk 腳本,input_file(s) 是使用 awk 進(jìn)行瀏覽的文件名。

模式和動(dòng)作

任何 awk 語句都是有模式和動(dòng)作組成。在一個(gè) awk 腳本中可能有很多語句,模式部分決定動(dòng)作語句何時(shí)觸發(fā)以及出發(fā)時(shí)間。處理即對數(shù)據(jù)進(jìn)行的操作。如果省略模式部分,動(dòng)作將時(shí)刻保持執(zhí)行狀態(tài)。模式可以是任何條件語句或符合語句或正則表達(dá)式。模式包括兩個(gè)特殊字段 BEGINEND。使用 BEGIN 語句設(shè)置計(jì)數(shù)和打印頭。BEGIN 語句使用在任何文本瀏覽動(dòng)作之前,之后文本瀏覽動(dòng)作一句輸入文本開始執(zhí)行。END 語句用來在 awk 完成瀏覽動(dòng)作后打印輸出文本總數(shù)和結(jié)尾狀態(tài)標(biāo)識(shí)。

域和記錄

使用 $1,$3 表示參照第一個(gè)和第三個(gè)域,注意這里使用逗號(hào)做域分割,如果希望打印一個(gè)有 5 個(gè)域的記錄的所有域,可使用 $0,意即所有域。為打印一個(gè)域或所有域,使用 printf 命令,這是一個(gè) awk 動(dòng)作。

模式和動(dòng)作

  • 模式:兩個(gè)特殊段 BEGINEND
  • 動(dòng)作:實(shí)際動(dòng)作大多在 {} 內(nèi)指明

輸出:

  1. 抽取域 命令:awk -F:'{print $1}' /etc/passwd 輸出:打印 /etc/passwd 目錄下的所有用戶名

  2. 保存輸出 awk -F:'{print $1}' /etc/passwd |tee user 使用 tee 命令,在輸出文件的同時(shí),輸出到屏幕

  3. 使用標(biāo)準(zhǔn)輸出 awk -F :'{print $1} /etc/passwd > user3  
  4. 打印所有記錄 awk -F :'{print $0} /etc/passwd`

  5. 打印單獨(dú)記錄 awk -F:'{print $1,$4}' /etc/passwd

  6. 打印報(bào)告頭 awk -F :'BEGIN{print "NAME\n"}{print $1}' /etc/passwd

  7. 打印結(jié)尾 awk -F:'{print $1}END{print "this is all users\n"}' /etc/passwd

條件操作符

  1. 匹配
    awk -F :'{if($1~/root/) print}' /etc/passwd
    分析:if($1~/roo/t) 表示如果 file 中包含 root,打印他
  2. 精確匹配使用符號(hào) ==
    awk -F:'{if($3==0) print}' /etc/passwd
  3. 不匹配!~
    awk -F:'{if($1!~/linuxone/) print}' /etc/passwd 精確不匹配!=
    awk -F:'{if($1!=/linuxone/) print}' /etc/passwd
  4. 小于<
  5. 小于等于<=
  6. 大于>
  7. 設(shè)置大小寫
    awk '/[Rr]oot' /etc/passwd
  8. 任意字符
    awk -F :'{f($1~/^...t/) print}' /etc/passwd 分析:if($1~/^...t/) 表示第四個(gè)字母是 t
  9. 或關(guān)系匹配awk -F
    '{if($1~/(squid|nagios)/) print}' /etc/passwd
  10. 行首
    awk '/^root/' /etc/passwd 分析:^root(行首包含 root)
  11. AND &&
    awk -F :'{if($1=="root"&&$3=="0") print}' /etc/passwd
  12. OR ||

內(nèi)置變量

變量名
含義
ARCC
命令行參數(shù)個(gè)數(shù)
ARGV
命令行參數(shù)列表
ENV |RON
支持隊(duì)列中的系統(tǒng)環(huán)境變量的使用
FNR
瀏覽文件的記錄數(shù)
FS
置頂分隔符,等價(jià)于 -F
NF
瀏覽記錄的域的個(gè)數(shù)
NR
一度的記錄數(shù)
OFS
輸出域分隔符
ORS
輸出記錄分隔符
RS
控制記錄分隔符

案例:

打印有多少行記錄
awk 'END{print NR}' /etc/passwd

設(shè)置輸入域到變量名
awk -F :'{name=$1;path=$7;if(name~/root/)print name"\tpath is :" path}' /etc/passwd

域值比較操作
awk '{if($6<$7) print $0}' input-file

修改文本域只顯示修改的記錄
awk -F :'{if($1=="root"){$1="nagios server";print}}' /etc/passwd

文件長度相加
ls -l | awk '/^[^d]/ {print $9"\t"$5}{tot+=$5}\ END {print"total kb:"tot}'

內(nèi)置的字符串函數(shù)

gsub(r,s)
在整個(gè) $0 中 s 替換 r
gsub(r,s,t)
在整個(gè) t 中 s 替換 r
index(s,t)
返回 s 中字符串 t 的第一位置
length(s)
返回 s 長度
match(s,r)
測試 s 中是否包含匹配 r 的字符串
split(s,a,fs)
在 fs 上將 s 分成序列 a
sub(s,)
用 $0 中最左邊也是最長的字符串替代
subtr(s,p)
返回字符串 s 中從 p 開始的后綴部分
substr(s,p,n)
返回字符串 s 中從 p 開始長度為 n 的后綴部分
  1. gsub
    awk 'gsub(/^root/,"netseek") {print}' /etc/passwd #將以 root 開頭的字符串替換為 netseek 并打印
    awk 'gsub(/0/,2){print}' /etc/passwd awk '{print gsub(/0/,2) $0}' /etc/fstab
  2. index
    awk 'BEGIN{print index("root","o")}' #查詢 o 在 root 字符串中出現(xiàn)的第一位置 awk -F :'$1=="root"{print index($1,"o")" "$1}' /etc/passwd awk -F :'{print index($1,"o") $1}' /etc/passwd
  3. length
    awk -F :'{print length($1)}' /etc/passwd wk -F :'$1=="root"{print length($1)"\t"$0}' /etc/passwd
  4. match(在 ANCD 中查找 C 的位置)
    awk 'BEGIN{print match("ANCD","C")}'
  5. split 返回字符串?dāng)?shù)組元素個(gè)數(shù)
    awk 'BEGIN{print split("123#456#789",array,"#")}'
  6. sub 只能替換指定域的第一個(gè) 0
    awk 'sub(/0/,2){print}' /etc/fstab
  7. substr 按照起始位置以及長度返回字符串的一部分
    awk 'BEGIN{print substr("www.baidu.com",5,9)}' #第五個(gè)子夫開始,取 9 個(gè)字符 awk 'BEGIN{print substr("www.baidu.com",5)}' #第五個(gè)位置開始,一直到最后

字符串屏蔽序列

符號(hào)
含義
\b
退格符
\f
走紙換頁
\n
新行
\r
回車
\t
tab 鍵 (四個(gè)空格)
\c
任意其他特殊字符
\ddd
八進(jìn)制

案例:
awk -F :'{print $1,"\b"$2,"\t"$3}' /etc/passwd
分析:print 和 printf 兩者效果不同

printf 修飾符

  • - :左對齊
  • width :域的步長 0 表示 0 步長
  • .prec :最大字符串長度,或小數(shù)點(diǎn)右邊的位數(shù)

awk printf 格式

符號(hào)
含義
%c
ASCII 字符
%d
整數(shù)
%e
科學(xué)計(jì)數(shù)法
%f
浮點(diǎn)數(shù)
%g
awk 決定使用哪種浮點(diǎn)數(shù)轉(zhuǎn)換,e 或者 f
%o
八進(jìn)制數(shù)
%s
字符串
%x
十六進(jìn)制
  1. 字符串轉(zhuǎn)換
    echo "65" | awk '{printf"%c\n",$0}' awk 'BEGIN{printf"%c\n",65}' awk 'BEGIN{printf"%f\n",999}'

  2. 格式化輸出
    awk -F :'{printf"%-15s %s\n",$1,$3}' /etc/passwd awk -F :'BEGIN{printf"USER\t\tUID\n"}{printf"%-15s %s\n",$1,$3}' /etc/passwd

  3. 向一行 awk 命令傳值
    who | awk '{if ($1==user) print $1 "you are connected :" $2}' user=$LOGNAME

  4. awk 腳本文件 (在文件名字后面加后綴.awk 翻遍區(qū)分)
    \#!/bin/awk -f
    BEGIN{
          FS=":"
          print "User\t\tUID"
          print "----------------"
    }
    \
    {printf"%-15s %s\n",$1,$3}
    \
    END{
          print "end"
    }

分析:awk 腳本文件開頭一般都是這樣的:#!/bin/awk -f 已經(jīng)指明了 -f 選項(xiàng)。執(zhí)行時(shí),直接在 awk 腳本名后面加要處理的文件名作為參數(shù)即可。