天天看點

Linux,shell,awk指令,文本格式化,文本報告生成器,代碼案例

作者:古怪今人

awk指令

awk

awk是一個強大linux指令,有強大的文本格式化能力,awk早期在Unix上實作,linux下是gawk,是GUN awk。

awk更是一門程式設計語言,支援條件判斷、數組、循環等功能。文本報告生成器(格式化文本),Linux上是gawk。

grep&sed&awk比較

grep,擅長單純的查找或比對文本内容;

sed,合适格式化文本内容,對文本進行複雜處理;

awk,更合适編輯、處理比對到的文本内容;

awk文法

awk [option] 'pattern[action]' file ...
awk 可選參數 模式 '條件動作' 檔案
action指的是動作,awk擅長文本格式化,且輸出格式化後的結果,最常用的動作就是print和printf。           

awk參數

-F,指定分割字段符;
-v,定義或修改一個awk内容的變量;
-f,從腳本檔案中讀取awk指令;           

關系運算法

<,小于;
<=,小于等于;
==,等于;
!=,不等于;
>=,大于等于;
>,大于
~,比對正則;
!~,不比對正則;           

内置變量(NF,NR,FS,FILENAME)

FS,輸入列(字段)分隔符,Field Split;
OFS,輸出列(字段)分隔符,Output Field Split;
RS,輸入記錄分隔符,預設是換行符(\n),Record Split;
ORS,輸出記錄分隔符,預設是換行符(\n),Output Record Split;
NF,字段總數,Number of Field,目前行數的個數字段數量;
NR,目前行數,行号,Number Row;
FNR,各檔案分别計數的行号;
RT,指定的分隔符;
FILENAME,輸出正在處理的檔案;
ARGC,指令行參數的個數;
ARGV,數組,儲存的是指令行所給定的各參數;           

格式化輸出

print和printf,printf格式化輸出,format格式的訓示符都是%開頭,後跟一個字元

%c: 顯示字元的ASCII碼;
%d,%i:十進制整數;
%e,%E:科學計數法顯示數值;
%f:顯示浮點數;
%g,%G:以科學計數法的格式或浮點數的格式顯示數值;
%s:顯示字元串;
%u: 無符号整數;
%%: 顯示%自身;

printf修飾符

左對齊(-),預設是右對齊;
顯示數值符号(+),printf %+d ;           

案例代碼

案例1:

#!/bin/bash

# 輸出第2列
echo "hello centos linux" | awk '{print $2}'
echo "hello centos linux" | awk -F ' ' '{print $2}'
echo "hello,centos,linux" | awk -F ',' '{print $2}'
echo "hello,centos,linux" | awk 'BEGIN{FS=","}{print $2}'
echo "史大郎|花和尚|林教頭" | awk 'BEGIN{FS="|"}{print $2}'
echo "史大郎|花和尚|林教頭" | awk 'BEGIN{FS="[|]+"}{print $2}'
# 輸出所有列
echo "史大郎|花和尚|林教頭" | awk 'BEGIN{FS="[|]+"}{print $1"==="$2"====="$3}'

# 寫入檔案
cat > words.txt <<'EOF'
張天師祈禳瘟疫 洪太尉誤走妖魔 王教頭私走延安府 九紋龍大鬧史家村
史大郎夜走華陰縣 魯提轄拳打鎮關西 趙員外重修文殊院 魯智深大鬧五台山
小霸王醉入銷金帳 花和尚大鬧桃花村 九紋龍剪徑赤松林 魯智深火燒瓦罐寺
花和尚倒拔垂楊柳 豹子頭誤入白虎堂 林教頭刺配滄州道 魯智深大鬧野豬林
柴進門招天下客 林沖棒打洪教頭 林教頭風雪山神廟 陸虞候火燒草料場
EOF

# 輸出第1,2,3列
awk '{print $1,$2,$3}' words.txt
# 每列加字首
awk '{print "第1列:"$1,"第2列:"$2,"第3列:"$3}' words.txt
# 每行都加字首
awk '{print "目前行的内容是:"$0}' words.txt
# 輸出第3行
awk 'NR==3' words.txt
# 輸出第4行第2列
awk 'NR==4{print $2}' words.txt
# 輸出第4行最後1列
awk 'NR==4{print $NF}' words.txt
# 輸出第3、4行最後1列
awk 'NR==3,NR==4{print $NF}' words.txt
# 輸出第3、4行最後1列和最後1列
awk 'NR==3,NR==4{print $1,$NF}' words.txt
# 輸出從2行到5行(從第2行到第5行,共4行)
awk 'NR==2,NR==5{print $1,$NF}' words.txt
# 輸出每行的行号
awk '{print NR,$0}' words.txt
awk 'NR==2,NR==5{print NR,$0}' words.txt
awk 'NR==2,NR==5{print NR,$1,$(NF-1),$NF}' words.txt           

案例2:

#!/bin/bash

# 生成檔案
cat /etc/passwd > passwd.txt

# 格式化輸出第1和最後1列
awk -F ':' '{print $1,$NF}' passwd.txt
# FS為變量
awk -v FS=":" '{print $1,$NF}' passwd.txt
# OFS輸出符号
awk -v FS=":" -v OFS="========" '{print $1,$NF}' passwd.txt
awk -F ':' -v OFS="========" '{print $1,$NF}' passwd.txt
# 含有轉義字元
awk -F ':' -v OFS='\t' '{print $1,$NF}' passwd.txt


# NR(行号),NF(列數)變量
awk -F ':' '{print NR,NF,$1,$(NF-1)}' passwd.txt
# FNR==>每個檔案輸出自己的行号
awk -F ':' '{print FNR,$1}' passwd.txt words.txt
awk -F ':' '{print FNR,NF,$1,$(NF-1)}' passwd.txt words.txt

# RS 和 ORS,輸出記錄分隔符
awk -v RS=' ' '{print NR,$1}' words.txt
awk -v ORS='----' '{print NR,$1}' words.txt
awk -v RS=' ' -v ORS='----' '{print NR,$1}' words.txt

# 每行追加檔案名
awk -F ' ' '{print FILENAME,$0}' passwd.txt           

案例3:

#!/bin/bash

# ARGC、ARGV變量
# ARGV表示一個數組,數組中儲存的是指令行所給的 參數
# 輸出前追加内容
awk 'BEGIN{print "開始操作~"}{print $0}' passwd.txt
# 輸出前追加,每行追加内容
awk 'BEGIN{print "開始操作~"}{print ARGV[0],$0}' passwd.txt
awk 'BEGIN{print "開始操作~"}{print ARGV[1],$0}' passwd.txt

# 輸出後追加内容
awk 'END{print "結束操作~"}{print $0}' passwd.txt

# 輸出前後都追加内容
awk 'BEGIN{print "開始操作~"}END{print "結束操作~"}{print $0}' passwd.txt

# 自定義變量(awk内部的變量)
awk -v name='佚名今人' 'BEGIN{print "who?",name}'
awk -v path=$PATH 'BEGIN{print "環境變量PATH",path}'

# 格式化輸出
awk '{printf "%s\n",$0}' passwd.txt
awk '{print $0}' passwd.txt
awk 'BEGIN{printf "%d\n",1,2,3,4,5}'
awk 'BEGIN{printf "%d\n%d\n",1,2,3,4,5}'
awk 'BEGIN{printf "%d\n%d\n%d\n",1,2,3,4,5}'

# 格式化輸出
# -右對齊
awk '{printf "第1列:%s 第2列:%s\n", $1, $2}' words.txt
awk -F ':' 'BEGIN{printf "%-25s\t%-25s\t\n","使用者","密碼"}{printf "%-25s\t %-25s\t\n",$1,$2}' passwd.txt

# awk指令,正規表達式用法
awk '/^root/{print $0}' passwd.txt
awk -F ':' '/^root/{print $1,$NF}' passwd.txt
# root行開始,daemon行結束
awk '/^root/,/^daemon/{print $0}' passwd.txt

# 統計Nginx的訪客數
# sort排序,uniq去重複,wc統計
#awk '{print $1}' access.log | sort -n | uniq | wc -l
# 統計前10的訪客
#awk '{print $1}' access.log | sort -n | uniq -c | sort -nc | head -10