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<NF; i++)
}

{for(i in list){
    action
}
}

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 命令

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,380评论 0 5
  • awk简介 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多...
    yeahuh阅读 3,955评论 0 7
  • 转载 原文的排版和内容都更加友好,并且详细,我只是在这里贴出了一部分留作自己以后参考和学习,如希望更详细了解AWK...
    XKirk阅读 3,210评论 2 25
  • Linux指令中文说明传送入口 整理自Linux指令中文说明 文本和数据进行处理的编程语言awk 是一种编程语言,...
    释闲人阅读 2,120评论 1 6
  • 90天践行目标: 目标:1.情绪控制。 每日记录:今天才上音乐课的时候老师进行了钢琴的启蒙。每人一台钢琴,可是宝宝...
    张晓虹阅读 303评论 0 0