awk的使用

awk是linux/unix一种适用于文本文件处理的工具。

gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。

使用命令格式与参数

Usage: awk [POSIX or GNU style options] -f progfile [--] file ... #从脚本文件中读取awk命令
Usage: awk [POSIX or GNU style options] [--] 'program' file ...#program可以是位于大括号内由换行符或分号隔开的多个命令
POSIX options:          GNU long options: (standard)
        -f progfile             --file=progfile  #从脚本读取awk程序
        -F fs                   --field-separator=fs #文件每行分隔符
        -v var=val              --assign=var=val #使用者自定义变量;-v a=1:自定义变量a
Short options:          GNU long options: (extensions)
        -b                      --characters-as-bytes
        -c                      --traditional
        -C                      --copyright
        -d[file]                --dump-variables[=file]
        -e 'program-text'       --source='program-text'
        -E file                 --exec=file
        -g                      --gen-pot
        -h                      --help
        -L [fatal]              --lint[=fatal]
        -n                      --non-decimal-data
        -N                      --use-lc-numeric
        -O                      --optimize
        -p[file]                --profile[=file]
        -P                      --posix
        -r                      --re-interval
        -S                      --sandbox
        -t                      --lint-old
        -V                      --version

基本概念:

记录: awk把每一个以换行符结束的行称为一个记录。

记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORS和RS中。

$0变量:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。

变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。

域: 记录中每个单词称做“域”,默认情况下以空格或tab分隔。awk可跟踪域的个数,并在内建变量NF中保存该值。如$ awk '{print $1,$3}' test将打印test文件中第一和第三个以空格分开的列(域)。

域分隔符: 内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。

$awk -F: '{print $1,$5}' test # 将打印以冒号为分隔符的第一,第五列的内容。可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中;
$awk -F'[:\t]' '{print $1,$3}' test # 表示以空格、冒号和tab作为分隔符。

开始awk的使用

测试文件test.txt,\t分隔

$ cat test.txt
num     name    letter  score
1       tom     A       85
2       joy     B       84
3       jack    C       83
4       bob     D       82
5       jerry   E       81

输出文件指定列

$ awk '{print $2,$3}' test.txt  #默认\s或\t
name letter
tom A
joy B
jack C
bob D
jerry E

自定义分隔符-F

$ awk -F \s '{print $1}' test.txt #文件\t分隔,使用\s分隔
num     name    letter
1       tom     A       85
2       joy     B       84
3       jack    C       83
4       bob     D       82
5       jerry   E       81

$ awk -F '\t' '{print $1}' test.txt
num
1
2
3
4
5

自定义变量 -v

$ awk -va=test '{print a,$1}' test.txt
test num
test 1
test 2
test 3
test 4
test 5

运算符

运算符 描述
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / % 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

比较表达式

$ awk '$2=="tom"' test.txt
1       tom     A       85

$ awk '$4>82' test.txt
num     name    letter  score
1       tom     A       85
2       joy     B       84
3       jack    C       83

y$ awk '$4>82 {print $2}' test.txt
name
tom
joy
jack
conditional expression1 ? expression2: expression3
例如:$ awk '{max = {$1 > $3} ? $1: $3: print max}' test。
如果第一个域大于第三个域,1就赋值给max,否则3就赋值给max。

  • 模式匹配

     awk 'pattern {action}' test   #对test中满足pattern的行进行action
    

    pattern

    • 正则表达式://
    • 关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
    • 模式匹配表达式:用运算符(匹配)和!(不匹配)。
    • 模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
 $ awk '$2 ~ /o/ {print $0}' test.txt  #第二列匹配有字符o
1       tom     A       85
2       joy     B       84
4       bob     D       82

$ awk 'BEGIN{IGNORECASE=1} /TOM/ {print $0}' test.txt  #忽略大小写
1       tom     A       85
$ awk '$2~/j/ {print $0}' test.txt
2       joy     B       84
3       jack    C       83
5       jerry   E       81

$ awk '$2!~/j/ {print $0}' test.txt
num     name    letter  score
1       tom     A       85
4       bob     D       82

范围模板

范围模板匹配从第一个模板的第一次出现到第二个模板的第一次出现之间所有行。如$ awk '/root/,/mysql/' test将显示root第一次出现到mysql第一次出现之间的所有行。

  • 内建变量

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)
ENVIRON 环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FS(Field Separator) 输入字段分隔符(默认空格 )
OFS (Out of Field Separator) 输出字段分隔符(默认空格)
RS (Record Separator) 输入记录分隔符(默认换行符), 默认将一行作为一条记录,可整段读取
ORS (Output Record Separate) 输出记录分隔符(默认换行符)
IGNORECASE 如果为真,则进行忽略大小写的匹配
FNR 当前文件中的记录号
NF(Number for Field) 一条记录的字段的数目
NR(Number of Record) 多个文件,已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
RLENGTH 由match函数所匹配的字符串的长度
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

8 个有力的 Awk 内建变量这篇文章对常用的awk内建变量进行了总结,非常有用。

$ awk '{print ARGC,FILENAME,NR,FNR,$0}' test.txt
2 test.txt 1 1 num      name    letter  score
2 test.txt 2 2 1        tom     A       85
2 test.txt 3 3 2        joy     B       84
2 test.txt 4 4 3        jack    C       83
2 test.txt 5 5 4        bob     D       82
2 test.txt 6 6 5        jerry   E       81
  • awk编程:

awk 'BEGIN{最先执行的操作} {需要执行的命令或代码} {需要执行的命令或代码}' file

变量

awk内建变量:直接使用;

-v定义变量:-v var=val;

变量赋值并传输给awk脚本:如$ awk -F: -f awkscript month=4 year=2004 test,上式的month和year都是自定义变量,分别被赋值为4和2004。

BEGIN{最先执行的操作}

awk操作命令之前需要执行的语句;通常用来改变内建变量的值,如OFS,RS和FS等,以及打印标题。

$ awk 'BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3} test。#在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。

$ awk 'BEGIN{print "TITLE TEST"} #打印标题。

{需要执行的命令或代码}

END{最后执行的操作}

awk 'END{print "The number of records is" NR}' test,上式将打印所有被处理的记录数。

例子:

$ vi test.awk
BEGIN{
print "---------------hello world!-------------\n"
}

{
printf "%15s %10s\n","I am writing:",$2
}

END{
print "---------------over!---------------\n"
}

运行程序:

$ awk -f test.awk test.txt
---------------hello world!-------------

  I am writing:       name
  I am writing:        tom
  I am writing:        joy
  I am writing:       jack
  I am writing:        bob
  I am writing:      jerry
---------------over!---------------
$ awk 'BEGIN{ print "Hello, world!"} {print "testing!"} END{print "over!"}' test.txt
Hello, world!
testing!
testing!
testing!
testing!
testing!
testing!
over!

awk条件语句

if语句

{if (condition){
                   action; action; ...
                     }
        }

if/else语句

{if (condition){
                   action; action; ...
                       }
        else{
                   action; action; ...
                       }
        }

if/else else if

 {if (condition){
                    action; action; ...
                   }
        else if (condition){
                    action; action; ...
                   }
        else if (condition){
                    action; action; ...
                   }
        else {
                   action; action; ...
             }
        }

循环

while循环

{while(condition){
    action
 }
}

for循环

{for (i = 1; i

awk的内建函数

字符串函数

sub() #字符串替换,发生在第一次匹配的时候;

sub(pattern,replace str)

sub(pattern,replace string, action range) #action range可以限定替换操作发生在文档那些部分。

gsub() #字符串替换,将所有匹配进行替换操作;

gsub(pattern,replace str)

gsub(pattern,replace str, action range)

index() #返回字符串第一次被匹配的索引,起始为1

index(str, substr)

length() #返回字符串长度

length( str )
length #文件当前记录字符串长度

substr() #截取字符串

substr( str, start)
substr( str, start, length)

match() #返回字符串匹配索引,失败返回0;可以使用内建变量:RSTART(初始匹配index) RSTART(匹配字符串长度)

match( str, regular expression )

toupper()

toupper(str) #字符串转换为大写

tolower(str) #字符串转换为小写

split()

split( str, array,separator ) #按给定的分隔符把字符串分割为一个数组array

split( str, array)

时间函数

systime()

systime() #返回从1970年1月1日开始到当前时间(不计闰年)的整秒数。

自定义函数

function( parameter, parameter, parameter, ... ) {
                        statements
                        return expression
        }

参考文献:

awk 用法(使用入门)

Linux awk 命令

你可能感兴趣的:(awk的使用)