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

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

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

awk
調(diào)用
1.調(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è)文件,并使阿瓦庫(kù)程序可執(zhí)行,然后用 awk 命令解釋器作為腳本的首行,以便通過(guò)鍵入腳本名成功來(lái)調(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 語(yǔ)句都是有模式和動(dòng)作組成.在一個(gè) awk 腳本中可能有很多語(yǔ)句,模式部分決定動(dòng)作語(yǔ)句何時(shí)觸發(fā)以及出發(fā)時(shí)間.處理即對(duì)數(shù)據(jù)進(jìn)行的操作.如果省略模式部分,動(dòng)作將時(shí)刻保持執(zhí)行狀態(tài).模式可以是任何條件語(yǔ)句或符合語(yǔ)句或正則表達(dá)式.模式包括兩個(gè)特殊字段 BEGIN 和 END.使用 BEGIN 語(yǔ)句設(shè)置計(jì)數(shù)和打印頭.BEGIN 語(yǔ)句使用在任何文本瀏覽動(dòng)作之前,之后文本瀏覽動(dòng)作一句輸入文本開始執(zhí)行.END 語(yǔ)句用來(lái)在 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è)特殊段 BEGIN 和 END
動(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

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

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

gsub(r,s)

在整個(gè)$0s替換r

gsub(r,s,t)

在整個(gè)ts替換r

index(s,t)

返回s中字符串t的第一位置

length(s)

返回s長(zhǎng)度

match(s,r)

測(cè)試s中是否包含匹配r的字符串

split(s,a,fs)

fs上將s分成序列a

sub(s,)

$0中最左邊也是最長(zhǎng)的字符串替代

subtr(s,p)

返回字符串s中從p開始的后綴部分

substr(s,p,n)

返回字符串s中從p開始長(zhǎng)度為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

  1. 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

  1. length
    awk -F : '{print length($1)}' /etc/passwd

wk -F : '$1=="root"{print length($1)"\t" $0}' /etc/passwd

  1. match(在 ANCD 中查找 C 的位置)
    awk 'BEGIN{print match("ANCD","C")}'

  2. split 返回字符串?dāng)?shù)組元素個(gè)數(shù)
    awk 'BEGIN{print split("123#456#789",array,"#")}'

  3. sub 只能替換指定域的第一個(gè) 0
    awk 'sub(/0/,2){print }' /etc/fstab

  4. substr 按照起始位置以及長(zhǎng)度返回字符串的一部分
    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 走紙換頁(yè)
\n 新行
\r 回車
\t tab鍵(四個(gè)空格)
\c 任意其他特殊字符
\ddd 八進(jìn)制

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

printf 修飾符

  • : 左對(duì)齊
    width : 域的步長(zhǎng) 0 表示 0 步長(zhǎng)
    .prec : 最大字符串長(zhǎng)度,或小數(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}'

  1. 格式化輸出
    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

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

  2. 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ù)即可。