Linux基礎之Shell--Awk使用(一)

一、簡述

AWK程序可用於選擇文件中的特定記錄並對它們執行操作。對文本處理有非常好的支持。功能強大。

二、awk 基本使用

1. 運行一個簡單的awk 程序

[root@localhost Awk0-script]# awk 'BEGIN{print "Don\47t Panic!"}'
Don't Panic!

注意: ’ '(單引號),否則執行錯誤

2. 通過文件的方式運行

[root@localhost Awk0-script]# vim demo-01  #編輯 demo-01 
BEGIN {print "Don't Panic!"}
[root@localhost Awk0-script]# awk -f demo-01  #運行 awk程序
Don't Panic!

3. 編寫可執行(Executable)的awk 程序

[root@localhost Awk0-script]# vim demo-02
[root@localhost Awk0-script]# chmod +x demo-02
############################################
	#!/bin/awk -f
	BEGIN {
	        print "Awk Executable Programs"
	}
##########################################
[root@localhost Awk0-script]# ./demo-02
Awk Executable Programs

4. awk 程序的註釋 “#”

[root@localhost Awk0-script]# awk 'BEGIN { print "hello Awk" }  # let's be cute'
> '
hello Awk

三、簡單的示例

1. 搜索文件中包含 ‘li’ 的記錄

[root@localhost Awk0-script]# awk '/li/ {print $0}' mail-list.txt
Amelia       555-5553     [email protected]    F
Broderick    555-0542     [email protected] R
Julie        555-6699     [email protected]   F
Samuel       555-3430     [email protected]        A

2. 輸出7個0~100之間的隨機數

[root@localhost Awk0-script]# awk 'BEGIN { for (i = 1; i <= 7; i++)
>  print int(101 * rand()) }'
24
29
85
15
59
19
81

3. 輸出所有記錄的字符數

[root@localhost Awk0-script]# awk '{print length($0) }' mail-list.txt
59
59
59
91

4. 統計當前文件使用的大小(bytes)

[root@localhost Awk0-script]# ll -l mail-list.txt
-rw-r--r--. 1 root root 752 Dec  8 16:28 mail-list.txt
# 查看單個文件所佔的字節數
[root@localhost Awk0-script]# ls -l mail-list.txt|awk '{print $5 " bytes"}'
752 bytes

#查看 當前目錄佔用的總字節數
[root@localhost Awk0-script]# ls -l ./ |awk 'BEGIN{print "The Directory Size(Bytes):"}{x+= $5}END{print x " bytes"}'
The Directory Size(Bytes):
1654 bytes

5. 打印當前文件的行數

[root@localhost Awk0-script]# awk 'END{print NR}' data.txt
17

6.輸出偶數行

[root@localhost Awk0-script]# awk 'NR % 2 == 0' data.txt  #奇數行 awk 'NR % 2 == 1' data.txt
Feb  15  32  24 226
Apr  31  52  63 420
Jun  31  42  75 492
Aug  15  34  47 316
Oct  29  54  68 525
Dec  17  35  61 401
Jan  21  36  64 620
Mar  24  75  70 495

7.統計當前目錄下12月的文件佔用的字節:

ls -l | awk '$6 == "Dec" { sum += $5 }END { print sum }'
1654

8. 複雜的awk處理

[root@localhost Awk0-script]#  echo a b | gawk 'BEGIN { FS = "" }
                  {
                      for (i = 1; i <= NF; i = i + 1)
                          print "Field", i, "is", $i,NF
                  }'
Field 1 is a 3
Field 2 is   3
Field 3 is b 3

9. 檢查當前系統用戶登錄的時間及登錄點

[root@localhost Awk0-script]# vim w_do.awk
BEGIN {
        FIELDWIDTHs = "9 12 6 10 6 7 7 35"
        printf "User      LOGIN      LOGIN_IP      TIME        \n"
        printf "---------------------------------------------\n"
}
NR>2{
        idle=$5
        sub(/^ +/,idle)
        if(idle== "")
                idle=0
        if(idle ~ /:/){
                split(idle,t,":")
                idle=t[1]*60+t[2]
        }
        if(idle~ /days/ )
                idle*=24*60*60
        printf "%2s %10s %15s %8s \n",$1,$2,$3,idle
}
[root@localhost Awk0-script]# w |awk -f w_do.awk
User      LOGIN      LOGIN_IP      TIME
---------------------------------------------
root      pts/0   192.168.10.102    6.00s

10. 根據需求截取數據長度

[root@localhost Awk0-script]# gawk -f fw.awk fw.in
3 12 34a bcde

### fw.awk #####
 BEGIN { FIELDWIDTHS = "2 3 4" }
 { print NF, $1, $2, $3 }
#############
@@@@ fw.in @@@@@@@
1234abcdefghi

awk 4.2版本以後支持最後一參數爲 " * " ,匹配餘下的字符串,
詳見: 4.6.3 Capturing Optional Trailing Data

11. 使用awk(gawk)解析csv文件

[root@localhost Awk0-script]# vim address.csv
Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA
[root@localhost Awk0-script]# vim process-csv.awk
########
BEGIN {
    FPAT = "([^,]+)|(\"[^\"]+\")"  # 匹配字段的正則表達式
}

{
    print "NF = ", NF  #輸出總的記錄數
    for (i = 1; i <= NF; i++) {   # 輸出記錄
        printf("$%d = <%s>\n", i, $i)
    }
}
#######
[root@localhost Awk0-script]# gawk -f process-csv.awk address.csv
NF= 7
$1= <Robbins>
$2= <Arnold>
$3= <"1234 A Pretty Street, NE">  ## 沒有正常顯示數據,需要去掉引號
$4= <MyTown>
$5= <MyState>
$6= <12345-6789>
$7= <USA>

改進之後的結果是:

###改進的方法是使用awk的 substr(str,index,len) 處理
if (substr($i, 1, 1) == "\"") {
    len = length($i)
    $i = substr($i, 2, len - 2)    # 獲取不包含雙引號的子串
}

[root@localhost Awk0-script]# gawk -f process-csv.awk address.csv
NF= 7
$1= <Robbins>
$2= <Arnold>
$3= <1234 A Pretty Street, NE>
$4= <MyTown>
$5= <MyState>
$6= <12345-6789>
$7= <USA>

12. 使用awk(gawk)處理多行數據

[root@localhost Awk0-script]# gawk -f addr.awk address
######## addr.awk #####
# Each line is one field.
BEGIN {RS = ""; FS = "\n"}  # RS:記錄分隔符   FS:字段分隔符(其爲空或者regx RS無效)

{
    printf "Name is:%s,Address is:%s,City and State are :%s \n",$1,$2,$3
}
######################
Name is:Jane Doe,Address is:123 Main Street,City and State are :Anywhere, SE 12345-6789
Name is:John Smith,Address is:456 Tree-lined Avenue,City and State are :Smallville, MW 98765-4321
[root@localhost Awk0-script]# cat address
Jane Doe
123 Main Street
Anywhere, SE 12345-6789

John Smith
456 Tree-lined Avenue
Smallville, MW 98765-4321

附錄:awk內建變量

變量(Variable) 說明(Description) 示例(Example)
$n 當前記錄的第n個字段,默認由FS分隔(tab或空格) awk ‘{print $1}’ file
$0 完整的輸入記錄 awk ‘{print $0}’ file
ARGC 命令行參數的數目
ARGIND 命令行參數當前文件的index awk ‘/^A/ {print ARGIND}’ mail-list.txt
ARGV 包含命令行參數的數組
CONVFMT 數字轉換格式(默認值爲%.6g)ENVIRON環境變量關聯數組
ERRNO 最後一個系統錯誤的描述
FIELDWIDTHS 字段寬度列表(用空格分隔)
FILENAME 當前文件名 awk ‘/^A/ {print FILENAME}’ file
FNR 各文件分別計數的行號 awk ‘/^A/ {print FNR}’
FS 字段分隔符(默認是任何空格)
IGNORECASE 如果爲1,則進行忽略大小寫的匹配
NF 一條記錄的字段的數目(即列)
NR 記錄數的行號
OFMT 數字的輸出格式(默認值是%.6g)
OFS 輸出記錄分隔符(輸出換行符),輸出時用指定的符號代替換行符
ORS 輸出記錄分隔符(默認值是一個換行符)
RLENGTH 由match函數所匹配的字符串的長度
RS 記錄分隔符(默認是一個換行符)
RSTART 由match函數所匹配的字符串的第一個位置
SUBSEP 數組下標分隔符(默認值是/034)

參考:
The GNU Awk User’s Guide

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章