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     amelia.zodiacusque@gmail.com    F
Broderick    555-0542     broderick.aliquotiens@yahoo.com R
Julie        555-6699     julie.perscrutabor@skeeve.com   F
Samuel       555-3430     samuel.lanceolis@shu.edu        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命令行参数当前文件的indexawk ‘/^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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值