linux condition用法,awk基本用法和工作原理详解

目录

1.awk介绍

2.awk基本用法和工作原理

3.awk的运用说明

1.awk介绍

awk是一种报表生成器,就是对文件进行格式化处理的,这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进而格式化显示。

在linux之上我们使用的是GNU awk简称gawk,并且gawk其实就是awk的链接文件,因此在系统上使用awk和gawk是一样。

通过man awk可以取得相关功能说明,还可以知道,gawk是一种过程式编程语言,支持条件判断、数组、循环等各种编程语言中所有可以使用的功能,因此我们还可以把awk称为一种脚本语言解释器。

2.awk基本用法和工作原理

gawk - pattern scanning and processing language:(模式扫描和处理语言)

基本用法:

格式1:awk [options] -f progfile [--] file ...

格式2:awk [options] [--] 'program' file ...

格式3awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

-f progfile,--file=progfile:从文件中来读取awk 的program

-F fs,--field-separator=fs:指明输入时用到的字段分割符

-v var=val,--assign=var=val:在执行program之前来定义变量

program:相当于编程语言,也就是处理后面文件的一系列操作语句

progfile:带有program或BEGIN等操作语句内容的文件

BEGIN:读取输入流前进行操作的标志

END:输入流读取完后进行操作的标志

pattern:模式,对输入流进行操作,实际上paogram就代表这pattern部分

action:动作语言,由多种语句组成,语句间用分号分割

工作原理:

从上面可以看到看似有三个格式,实际上总的来说就一个格式,就是格式3,因为格式1和2展开后,也就是格式3。

格式:awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

第一步:执行[option]相关内容,也就是-f,-F,-v选项内容。

第二步:执行BEGIN{action;… } 语句块中的语句。BEGIN 语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN 语句块中。

第三步:从文件或标准输入(stdin) 读取每一行,然后执行pattern{action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern 语句块,则默认执行{ print } ,即打印每一个读取到的行,awk 读取的每一行都会执行该语句块。

第四步:当读至输入流末尾时,也就是所有行都被读取完执行完后,再执行END{action;…} 语句块。END 语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END 语句块中完成,它也是一个可选语句块。

3.awk的运用

1.awk中的变量

变量分为内置变量和自定义变量,但只要是变量都是用的选项-v。先选常用的内置变量说明下,然后说下自定义的变量。

内置变量:

FS:输入字段分隔符,默认为空白字符,这个想当于-F选项。分隔符可以是多个,用[]括起来表示,如:-v FS="[,./-:;]"

OFS:输出字段分隔符,默认为空白字符,分隔符可以是多个,同上

RS :输入记录(所认为的行)分隔符,指定输入时的换行符,原换行符仍有效,分隔符可以是多个,同上

ORS :输出记录(所认为的行)分隔符,输出时用指定符号代替换行符,分隔符可以是多个,同上

NF:字段数量

NR:记录数(所认为的行)

FNR :各文件分别计数, 记录数(行号)

FILENAME :当前文件名

ARGC:命令行参数的个数

ARGV :数组,保存的是命令行所给定的各参数

自定义变量(区分字符大小写):

在'{...}'前,需要用-v var=value:awk -v var=value '{...}'

在program 中直接定义:awk '{var=vlue}'

下面针对每个变量都举个例子:

awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd

awk –F: '{print $1,$3,$7}’ /etc/passwd

awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd

awk -v RS=' ' ‘{print }’ /etc/passwd

awk -v RS="[[:space:]/=]" '{print }' /etc/fstab |sort

awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd

awk -F: ‘{print NF}’ /etc/fstab, 引用内置变量不用$

awk -F: '{print $(NF-1)}' /etc/passwd

awk '{print NR}' /etc/fstab ; awk 'END{print NR}' /etc/fstab

awk '{print FNR}' /etc/fstab /etc/inittab

awk '{print FNR}' /etc/fstab /etc/inittab

awk '{print FILENAME}’ /etc/fstab

awk '{print ARGC}’ /etc/fstab /etc/inittab

awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab

awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab

awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab

awk -v test='hello gawk' '{print test}' /etc/fstab

awk -v test='hello gawk' 'BEGIN{print test}'

awk 'BEGIN{test="hello,gawk";print test}'

awk –F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd

awk -F: '{sex="male";age=18;print $1,sex,age}' /etc/passwd

echo "{print script,\$1,\$2}" > awkscript

awk -F: -f awkscript script=“awk” /etc/passwd

2.awk的print和printf

print和printf都是打印输出的,不过两者用法和显示上有些不同而已。

print 格式:print item1,item2, ...

printf格式:printf “FORMAT ”,item1,item2, ...

要点:

1.逗号为分隔符时,显示的是空格;

2.分隔符分隔的字段(域)标记称为域标识,用$0,$1,$2,...,$n表示,其中$0 为所有域,$1就是表示第一个字段(域),以此类推;

3.输出的各item可以字符串,也可以是数值,当前记录的字段,变量或awk 的表达式等;

4.如果省略了item ,相当于print $0

5.对于printf来说,必须指定FORMAT,即必须指出后面每个itemsN的输出格式,且还不会自动换行,需要显式则指明换行控制符"\n"

printf的格式符和修饰符:

%c:显示字符的ASCII码

%d, %i:显示十进制整数

%e, %E:显示科学计数法数值

%f:显示为浮点数

%g, %G:以科学计数法或浮点形式显示数值

%s:显示字符串

%u:无符号整数

%%:显示%自身

#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f

-:左对齐(默认右对齐);%-15s,就是以左对齐方式显示15个字符长度

+:显示数值的正负符号 %+d

这里也举个示例:

awk '{print "hello,awk"}'

awk –F: '{print}' /etc/passwd

awk –F: ‘{print “wang”}’ /etc/passwd

awk –F: ‘{print $1}’ /etc/passwd

awk –F: ‘{print $0}’ /etc/passwd

awk –F: ‘{print $1”\t”$3}’ /etc/passwd

tail –3 /etc/fstab |awk ‘{print $2,$4}’

awk -F: ‘{printf "%s",$1}’ /etc/passwd

awk -F: ‘{printf "%s\n",$1}’ /etc/passwd

awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd

awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd

awk -F: ‘{printf “Username: %s,UID:%d\n",$1,$3}’ /etc/passwd

awk -F: ‘{printf "Username: %15s,UID:%d\n",$1,$3}’ /etc/passwd

awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd

lsmod

awk -v FS=" " 'BEGIN{printf "%s %26s %10s\n","Module","Size","Used by"}{printf "%-20s %13d %5s %s\n",$1,$2,$3,$4}' /proc/modules

3.awk的操作符

算术操作符:x+y, x-y, x*y, x/y, x^y, x%y

赋值操作符:=, +=, -=, *=, /=, %=, ^=,++, --

比较操作符:==, !=, >, >=,

模式匹配符:~ :左边是否和右边匹配包含;!~ :是否不匹配

逻辑操作符:与:&& ;或:|| ;非:!

条件表达式(三目表达式):selector ? if-true-expression : if-false-expression

示例:

awk –F: '$0 ~ /root/{print $1}‘ /etc/passwd

awk '$0~“^root"' /etc/passwd

awk '$0 !~ /root/‘ /etc/passwd

awk –F: ‘$3==0’ /etc/passwd

awk–F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd

awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd

awk -F: ‘!($3==0) {print $1}' /etc/passwd

awk -F: ‘!($3>=500) {print $3}’ /etc/passwd

awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SySUSEr";printf "%15s:%-s\n",$1,usertype}' /etc/passwd

4.awk的pattern

awk语句中是根据pattern条件,过滤匹配的行,再做处理。

1.未指定:表示空模式,匹配每一行

2./regular expression/:仅处理能够模式匹配到的行,支持正则表达式,需要用/ /括起来

3.关系表达式:结果为“真”才会被处理。真:结果为非0值,非空字符串。假:结果为空字符串或0值

4./pat1/,/pat2/:startline,endline ,行范围,支持正则表达式,不支持直接给出数字格式

5.BEGIN{}和END{}:BEGIN{} 仅在开始处理文件中的文本之前执行一次。END{}仅在文本处理完成之后执行 一次

示例:

awk '/^UUID/{print $1}' /etc/fstab

awk '!/^UUID/{print $1}' /etc/fstab

awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd

awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passw

awk -F: 'i=1;j=1{print i,j}' /etc/passwd

awk ‘!0’ /etc/passwd ; awk ‘!1’ /etc/passwd

awk –F: '$3>=1000{print $1,$3}' /etc/passwd

awk -F: '$3<1000{print $1,$3}' /etc/passwd

awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd

awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd

awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3}END{print "end file"}' /etc/passwd

awk -F: 'BEGIN{print " USER USERID"}{printf "|%8s| %10d|\n",$1,$3}END{print "END FILE"}' /etc/passwd

awk -F : '{print "USER USERID“;print $1":"$3} END{print"end file"}' /etc/passwd

awk -F: 'BEGIN{print " USER UID \n---------------"}{print $1,$3}' /etc/passwd

awk -F: 'BEGIN{print " USER USERID\n----------------------"}{printf "|%8s| %10d|\n",$1,$3}END{print "----------------------\nEND FILE"}' /etc/passwd

awk -F: 'BEGIN{print " USER UID \n---------------"}{print $1,$3}'END{print "=============="} /etc/passwd

seq 10 |awk ‘i=0’

seq 10 |awk ‘i=1’

seq 10 | awk 'i=!i‘

seq 10 | awk '{i=!i;print i}‘

seq 10 | awk ‘!(i=!i)’

seq 10 |awk -v i=1 'i=!i'

5.awk的action

awk中的action可以分为以下5类:

1.表达式语句,包括算术表达式和比较表达式,就是用进行比较和计算的。

2.控制语句,用作进行控制,典型的就是if else,while等语句,和bash脚本里面用法差不多。

3.输入语句,用来做为输入,变量赋值就算是。

4.输出语句,用来输出显示的,典型的是print和printf

5.组合语句,这个很多理解,就是多种语句的组合

下面就具体说下一些语句的具体内容,也没有分割那么清晰,但都属于action范围:

1.awk的if-else

语法:

{if(condition){statement;…}}:条件满足就执行statement

{if(condition){statement1;…}{else statement2}}:条件满足执行statement1,不满足执行statement2

{if(condition1){statement1}else if(condition2){statement2}else{statement3}}:条件1满足执行statement2,不满足条件1但满足条件2执行statement2,所用条件都不满足就执行statement3

示例:

awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd

awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd

awk '{if(NF>5) print $0}' /etc/fstab

awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1}else{printf "root or Sysuser: %s\n",$1}}' /etc/passwd

awk -F: '{if($3>=1000) printf "Common user: %s\n",$1;else printf "root or Sysuser: %s\n",$1}' /etc/passwd

df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print $1,$5}‘

awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'

2.awk的while和do-while

语法:

while(condition){statement;…}:条件为“真”时,进入循环;条件为“假”时, 退出循环

do {statement;…}while(condition):无论真假,至少执行一次循环体。当条件为“真”时,退出循环;条件为“假”时,继续循环

示例:

awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg

awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg

awk 'BEGIN{ total=0;i=0;do{total+=i;i++}while(i<=100);print total}‘

3.awk的for

语法:

for(expr1;expr2;expr3) {statement;…}:expr1为变量赋值,如var=value,初始进行变量赋值;expr2为条件判断语句,j<=10,满足条件就继续执行statement;expr3为迭代语句,如j++,每次执行完statement后就迭代增加

for(var in array) {for-body}:变量var遍历数组,每个数组中的var都会执行一次for-body

示例:

awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

awk '/^[^#]/{type[$3]++}END{for(i in type)print i,type[i]}' /etc/fstab

awk -v RS="[[:space:]/=,-]" '/[[:alpha:]]/{ha[$0]++}END{for(i in ha)print i,ha[i]}' /etc/fstab

4.awk的switch

switch 语句,相当于bash中的case语句。

语法:

switch(expr) {case VAL1 or /REGEXP/:statement1; case VAL2 or /REGEXP2/: statement2;...; default: statementn}:若expr满足 VAL1 or /REGEXP/就执行statement1,若expr满足VAL2 or /REGEXP2/就执行statement2,以此类推,执行statementN,都不满足就执行statement

5.awk的break、continue和next

break 和continue,用于条件判断循环语句,next是用于awk自身循环的语句。

break[n]:当第n次循环到来后,结束整个循环,n=0就是指本次循环

continue[n]:满足条件后,直接进行第n次循环,本次循环不在进行,n=0也就是提前结束本次循环而直接进入下一轮

next:提前结束对本行的处理动作而直接进入下一行处理

示例:

awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}‘

awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}‘

awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

6.awk的数组

awk的数组是关联数组,格式为:

array[index-expression]:arry为数组名,index-expression为下标。

实际上index-expression可使用任意字符串,字符串要使用双引号括起来;如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为“空串”。

若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历。

若要遍历数组中的每个元素,要使用for循环:for(var in array) {for-body},使用for循环会使var 会遍历array的每个索引。此时要显示数组元素的值,则要使用array[var]。

示例:

awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}‘

awk '!arr[$0]++' dupfile

awk '{!arr[$0]++;print $0, arr[$0]}' dupfile

awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}‘

netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state) { print i,state[i]}}'

awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}'/var/log/httpd/access_log

7.awk的函数

awk的函数有许多,除了系统自带的内建函数还有就是用户自定义的函数,这里挑选几个常���的函数。

rand():返回0 和1 之间一个随机数

srand():生成随机数种子

int():取整数

length([s]):返回指定字符串的长度

sub(r,s,[t]):对t字符串进行搜索,r表示的模式匹配的内容,并将第一个匹配的内容替换为s

gsub(r,s,[t]):对t字符串进行搜索,r表示的模式匹配的内容,并全部替换为s所表示的内容

split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array 所表示的数组中,第一个索引值为1, 第二个索引值为2,…也就是说awk的数组下标是从1开始编号的。

substr(s,i,[n]):从s所表示的字符串中取子串,取法:从i表示的位置开始,取n个字符。

systime():取当前系统时间,结果形式为时间戳。

system():调用shell中的命令。空格是awk中的字符串连接符,如果system 中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用"" 引用 起来。

示例:

awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'

echo "2008:08:08 08:08:08" | awk 'sub(/:/,“-",$1)'

echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,“-",$0)'

netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'

awk BEGIN'{system("hostname") }'

awk 'BEGIN{score=100; system("echo your score is " score) }'

自定义函数,格式为

function fname (arg1,arg2 , ...){

statements

return expr

}

自定义函数中fname为函数名,arg1...为函数的参数,statements是动作语言,return expr为由statements的结果从而决定最终函数所显示的内容。

示例:

cat fun.awk

function max(v1,v2){

v1>v2?var=v1:var=v2

return var

}

BEGIN{a=3;b=2;print max(a,b)}

awk –f fun.awk

6.awk的脚本

awk的脚本就是将awk程序写成脚本形式,来直接调用或直接执行。例如上面写自定义函数的样子也算是脚本。

格式1:

BEGIN{} pattern{} END{}

格式2:

\#!/bin/awk -f

\#add 'x' right

BEGIN{} pattern{} END{}

格式1假设为f1.awk文件,格式2假设为f2.awk文件,那么用法是:

awk [-v var=value] f1.awk [file]

f2.awk [-v var=value] [var1=value1] [file]

对于awk [-v var=value] f1.awk [file]来说,很好理解,就是把处理阶段放到一个文件而已,真正展开后,也就是普通的awk语句。

对于f2.awk [-v var=value] [var1=value1] [file]来说, [-v var=value]是在BEGIN之前设置的变量值,[var1=value1]是在BEGIN过程之后进行的,也就是说直到首行输入完成后,这个变量才可用,这就想awk脚本黄总传递参数了。

示例:

cat f1.awk

{if($3>=1000)print $1,$3}

awk -F: -f f1.awk /etc/passwd

cat f2.awk

#!/bin/awk –f

#this is a awk script

{if($3>=1000)print $1,$3}

#chmod +x f2.awk

f2.awk –F: /etc/passwd

cat test.awk

#!/bin/awk –f

{if($3 >=min && $3<=max)print $1,$3}

#chmod +x test.awk

test.awk -F: min=100 max=200 /etc/passwd

到此为止算是差不多了,实际上awk的内容好多,这里只是写了所知道的,更详细的可看man awk来获取更加全面的知识。上述若有错误的地方,欢迎提出!谢谢~

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值