AWK ( 二 )

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AWK ( 二 )相关的知识,希望对你有一定的参考价值。

awk的匹配条件

在awk中,0表示假,1表示真。 只有为真时,才会执行program代码块。

变量未声明,变量值为空,变是值为0.pattern条件都是返回为0(假)

下面的3种情况都为假,都不会有输出结果。

#awk -v i="" ‘i{print $0}‘ /etc/passwd
#awk -v i=0 ‘i{print $0}‘ /etc/passwd
#awk  ‘i{print $0}‘ /etc/passwd
以下情况,变量A并没有定义,但是在前面加上!,相当于把假取反,也就是真了。所以命令有执行结果。
#awk  ‘!A{print $0}‘ /etc/passwd 等价于 #awk  ‘!A‘ /etc/passwd

一些比较烧脑的写法

#awk ‘BEGIN{i=0;print !i++,i}‘  解析:i=0,为假,先把i取反,变为真,第一个结果为1,再i++ (0+1=1) ,第二个结果为1
1 1

#awk ‘BEGIN{i=0;print !++i,i}‘ 解析:i=0,为假,先++i(0+1=1),再把i取反,变为假,第一个结果为0,再++i(0+1=1) ,第二个结果为1
0 1

#awk ‘BEGIN{i=-1;print !++i,i}‘ 解析:i=-1,不为空,也不为0,为真,先++i(-1+1=0)  ,再把i取反,变为真,第一个结果为1,再++i(-1+1=0) ,第二个结果为0
1 0

#awk ‘BEGIN{i=-1;print !i++,i}‘ 解析:i=-1,不为空,也不为0,为真,先把i取反,变为假,第一个结果为0,再i++(-1+1=0) ,第二个结果为0
0 0

利用awk 打印奇数行

#seq 10 | awk ‘i=!i‘
1
3
5
7
9

来解读下吧:

根据文章最开头讲的,在awk中,0表示假,1表示真。 只有为真时,才会执行program代码块。

当awk开始处理第一行时,变量 i 未声明,值为"空",表示假,但是i取反了,变为真了,所以会执行program的动作,但是动作省略了,因此就是默认print $0,也就是输出第一行。

当处理第二行文本时,i 为真,取反后,i 为假,所以第二行没有执行program的动作,最终只打印了奇数行。

为了能够更加直观的看到上述过程0和1的变化,将i的值打印出来。

#seq 10 | awk ‘{i=!i;print i,$0}‘
1 1
0 2
1 3
0 4
1 5
0 6
1 7
0 8
1 9
0 10

#seq 10 | awk ‘++I%2‘
1
3
5
7
9

#seq 10 | awk -v i=0 ‘i=!i‘
1
3
5
7
9

#seq 10 | awk ‘NR%2‘
1
3
5
7
9

利用awk 打印偶数行

#seq 10 | awk -v i=1 ‘i=!i‘
2
4
6
8
10
上面的例子,用更详细的过程打印出来,当i=0时,不会输出那一行。
#seq 10 | awk -v i=1 ‘{i=!i;print i,$0}‘
0 1
1 2
0 3
1 4
0 5
1 6
0 7
1 8
0 9
1 10

#seq 10 | awk ‘i++%2‘
2
4
6
8
10

#seq 10 | awk ‘!(NR%2)‘
2
4
6
8
10

awk控制语句

三目表达式

语法:

条件 ? 条件为 真 时执行: 条件为 假 时执

也可以理解为:
表达式1 ? 表达式1为 真 时执行的表达式A: 表达式1为 假 时执行的表达式B

例子:

awk -F: ‘{usertype=$3<500? "系统用户" : "普通用户" ;print $1,$3,usertype}‘ /etc/passwd

root 0 系统用户
bin 1 系统用户
nfsnobody 65534 普通用户
saslauth 499 系统用户
hunk 500 普通用户

#awk ‘BEGIN{grep hunk44 ?var="用户存在":var="用户不存在";print var}‘
用户不存在

#awk -F: ‘{$3<500 ?sum1++:sum2++;}END{print "系统用户数:"sum1,"普通用户数:"sum2}‘ /etc/passwd
系统用户数:19 普通用户数:5

组合语句

所谓的组合语句,就是大括号内有多条指令。指令之间用;分号分隔

如:

awk -F: ‘{print $1}‘ /etc/passwd   >  单条语句
awk -F: ‘{print "uid: "$3 ; print $1}‘ /etc/passwd  > 组合语句

if 条件判断语句

if语法:

if(条件){语句1;语句2;...}
如果{}中只有一条语句,可以省略{},反之则必须存在{}
if语句必须放在{}内

例子:

awk -F: ‘{if($3<5)print $0}‘ /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

awk -F: ‘{if($3<5){print "abc";print $0}}‘ /etc/passwd
    abc
    root:x:0:0:root:/root:/bin/bash
    abc
    bin:x:1:1:bin:/bin:/sbin/nologin

这里构建一个特殊的文件

#vim df.txt 
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda3        8652808 1905000   6301600  24% /
tmpfs/dev/sda6             113972       0    113972   0%    > 需要注意的是,这一行中的/dev/sda并不是在行首
/dev/sda1         487652   35608    426444   8% /boot

#awk ‘{if($0 ~ "^/dev/sda")print $1,$5}‘ df.txt 
/dev/sda3 24%
/dev/sda1 8%

#awk ‘{if($0 ~ "/dev/sda")print $1,$5}‘ df.txt 
/dev/sda3 24%
tmpfs/dev/sda6 0%
/dev/sda1 8%

所以,现在清楚 ~ 正则匹配模式默认指的是包含了吧

另外,前面说过,在正则匹配模式时,可以使用/ / 和 " " 来引用正则,当下面这种情况出现时,建议使用不一样的引用符号呢 
#awk ‘{if($0 ~ //dev/sda/)print $1,$5}‘ df.txt 
awk: {if($0 ~ //dev/sda/)print $1,$5}
awk:                    ^ syntax error

当然,使用转义也行,只不过看起来没有那么清晰而已
#awk ‘{if($0 ~ /\/dev\/sda/)print $1,$5}‘ df.txt 
/dev/sda3 24%
tmpfs/dev/sda6 0%
/dev/sda1 8%

判断磁盘利用率超出某个阀值
#df|awk -F "[ %]+" ‘/^\/dev\/sd/{if($5 > 20)print $1,$5"%"}‘  > 最后这个%仅仅作为字符串显示
/dev/sda3 24%

在Centos7中的awk版本,默认在比较数字时,会忽略数字后面的字符,直接进行比较
#df|awk ‘/^\/dev\/sd/{if($5 > 20)print $1,$5}‘
/dev/sda3 20%
/dev/sda1 23%

而同样的语句,在Centos6的版本是不生效的,请注意
#df|awk ‘/^\/dev\/sd/{if($5 > 20)print $1,$5}‘
/dev/sda3 24%
/dev/sda1 8%

if..else语法:

if(条件){语句1;语句2;...}else {语句3;语句4;...}
如果{}中只有一条语句,可以省略{},反之则必须存在{}
if语句必须放在{}内

例子:

#df|awk -F "[ %]+" ‘/^\/dev\/sd/{if($5 > 20){print $1,$5} else {print $1,$5,"未超出"}}‘
/dev/sda3 24
/dev/sda1 8 未超出

if..elseif..else语法

if(条件1){语句1;语句2;...}else if(条件2){语句3;语句4;...}else {语句5;语句6;...}
如果{}中只有一条语句,可以省略{},反之则必须存在{}
if语句必须放在{}内
可以存在多个elseif

例子:

命令有点长,慢慢按语法读就会懂了

#awk -F "[ %]+" ‘/^\/dev\/sd/{if($5 > 90 ){print $1,$5,"达到90%以上"} else if($5 > 60) {print $1,$5,"达到60%以上" } else if($5 > 20) {print $1,$5,"达到20%以上" } else {print $1,$5,"未超出指定阀值"}}‘ df.txt
/dev/sda3 20 未超出指定阀值
/dev/sda2 70 达到60%以上
/dev/sda6 100 达到90%以上
/dev/sda1 23 达到20%以上

while循环

语法:

while(条件){语句1;…}

条件“真”,进入循环;条件“假”,退出循环

例子:

统计以root开头的行,每列的字符长度
#awk -F: ‘/^root/{i=1;while(i<=NF){print $i,length($i);i++}}‘ /etc/passwd

root 4
x 1
0 1
0 1
root 4
/root 5
/bin/bash 9

do..while循环

语法:

do{语句1;…}while(条件)

无论条件真假,至少执行一次do内的循环体语句
#awk ‘BEGIN{i=100;sum=0;do{sum+=i;i++}while(i<=100);print sum}‘
首先执行一次do里面的语句,此时sum=100,再来判断while的条件,此时的i++后等于101,while的条件为假,后续也不会再执行do的语句块了。因此最终的循环结果为100

for循环

语法1:

for(初始化值;条件;变化方式) {语句1;…}
计算0-100相加的和
#awk ‘BEGIN{for(i=0;i<=100;i++){sum+=i};print sum}‘
5050

既然学了那么多的循环计算,现在来作个性能比较。计算一千万次。
awk

#time awk ‘BEGIN{for(i=0;i<=10000000;i++){sum+=i};print sum}‘
50000005000000

real    0m1.012s
user    0m1.009s
sys 0m0.001s

bash 中的for

#time for((sum=0,i=0;i<=10000000;i++));do sum=$[sum+i];done;echo $sum

real    1m19.933s
user    1m15.831s
sys 0m3.846s
50000005000000

调用bc计算器

#time (seq -s "+" 10000000|bc)
50000005000000

real    0m7.862s
user    0m5.485s
sys     0m0.458s

awk的效率真不是吹的,以后涉及到循环计算的时候记得使用。

语法2 (遍历数组)

for(变量 in 数组) {for-body}

switch

语法: (类似于bash脚本中的case)

switch (表达式) { case "表达式值1" 或 /正则1/ : 语句1...[ default: 都不匹配将执行此语句2 ] }
#awk -F: ‘{ switch($1){ case /^root/: print $0,"匹配case值1"; case "ftp": print $0,"匹配case值2"; default: print "默认条件不匹配"} }‘ /etc/passwd
root:x:0:0:root:/root:/bin/bash 匹配case值1
root:x:0:0:root:/root:/bin/bash 匹配case值2    > 为啥会匹配这一行,因为没有跳出循环。请看下面的break
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 匹配case值2

#awk -F: ‘{ switch($1){ case /^root/: { print $0,"匹配case值1"; break }; case /^ftp/: { print $0,"匹配case值2"; break }; case /^hunk/: { print $0,"匹配case值3"; break }; default: print "默 认条件不匹配" } }‘ /etc/passwd

root:x:0:0:root:/root:/bin/bash 匹配case值1
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 匹配case值2
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
默认条件不匹配
hunk88:x:1000:1001::/home/hunk88:/bin/bash 匹配case值3
hunk89:x:1001:50::/home/hunk89:/bin/bash 匹配case值3
hunk3:x:1002:1002::/home/hunk3:/bin/bash 匹配case值3
hunk4:x:1003:1003::/home/hunk4:/bin/bash 匹配case值3

break

作用:跳出"整个"循环

#awk ‘BEGIN{for(i=0;i<=5;i++){if(i==4)break;print i}}‘
0
1
2
3

当i=4的时候,后续的循环将不再进行,直接结束了本层的for循环

continue

作用:跳出"本次"循环

#awk ‘BEGIN{for(i=0;i<=5;i++){if(i==4)continue;print i}}‘
0
1
2
3
5

当i=4的时候,直接跳过本次循环,直接进行第5次循环

如果有多层循环,可以使用诸如以下格式的语法,控制每一层的循环

brean n(数字)
continue n(数字)

next

作用:提前结束对本行处理而直接进入下一行处理(awk本身就是一种逐行循环)

next与continue有些类似,只是,continue是针对"循环"而言的,而next是针对"逐行处理"的awk模式而言的,因此,next是不可以出现在BEGIN和END语句块中的

#awk ‘{if(/line 2/)next;print $0}‘ 1.txt 
line 1
line 3
line 4
line 5

awk数组

一般语言中的数组元素的下标以数字表示,默认从0开始。awk使用的数组是"关联数组",也就是说不是以数字作为下标,"数字"下标会被awk转换为"字符串"。

语法:

数组名[索引表达式]
数组名["字符串"]="值"    > 可使用任意字符串;字符串要使用双引号括起来

如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空的字符串”

#awk ‘BEGIN{demo["A"]="num1";demo["B"]="num2"; print demo["B"]}‘
num2

#awk ‘BEGIN{demo["A"]="num1";demo["B"]="num2"; print demo["C"]}‘

只会打印出一行空值的行,肯定是看不见的。

判断数组中是否存在某元素

语法:

索引 in 数组名

以上面的一个例子来继续演示

#awk ‘BEGIN{demo["A"]="num1";demo["B"]="num2"; if("B" in demo){print "存在数组中"}else {print "不在数组中"}}‘
存在数组中

#awk ‘BEGIN{demo["A"]="num1";demo["B"]="num2"; if("C" in demo){print "存在数组中"}else {print "不在数组中"}}‘
不在数组中

妙用awk数组去除文件中重复的行

#cat 1.txt 
line 1
line 3
line 2
line 3
line 3
line 4
line 5
line 5

#awk ‘!arr[$0]++‘ 1.txt 
line 1
line 3
line 2
line 4
line 5

当然,sort 命令也是可以做到的哦
#sort -u 1.txt 
line 1
line 2
line 3
line 4
line 5

这个地方用uniq去除就是不对的哦,因为-u指的是 仅显示不曾重复的行 ,那2行5是连续出现的,就是重复的行了。
#uniq -u 1.txt 
line 1
line 3
line 2
line 4

遍历数组中的每个元素

语法:

for (变量 in 数组) {for 语句块}
#awk ‘BEGIN{demo["A"]="123";demo["B"]="456";demo["C"]="789";for(i in demo){print i,demo[i]}}‘
A 123
B 456
C 789

demo数组中一共有3个元素

删除数组和删除数组元素

delete语法:

delete demo 删除整个数组
delete["元素"] 删除某个元素
#awk ‘BEGIN{demo["A"]="123";demo["B"]="456";demo["C"]="789";delete demo["C"];for(i in demo){print i,demo[i]}}‘
A 123
B 456

实例演示

统计每个匹配的字符的数量

这里以系统登录的IP为例:使用之前学习过的sort和uniq命令的组合可以完成此任务

#time last|awk ‘$3 ~ /[0-9]/{print $3}‘|sort -r|uniq -c
     43 192.168.7.200
     31 192.168.5.1
      8 192.168.4.1
      1 172.18.105.86

用时如下:
real    0m0.009s
user    0m0.006s
sys     0m0.003s

以awk来处理的话:利用之前讲的 数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空的字符串”,再对此元素再行自相加

语法公式:

awk ‘{ 数组名[统计的字段]++ } END { for (i in 数组名){ print i, 数组名[i]} }‘
#time last|awk ‘$3 ~ /[0-9]/{ ip[$3]++ } END { for(i in ip){ print ip[i],i  } }‘
31  192.168.5.1
1   172.18.105.86
43  192.168.7.200
8   192.168.4.1

real    0m0.004s
user    0m0.003s
sys     0m0.000s

统计apahce httpd中访问日志的IP数量

#time cut -d" " -f1 /var/log/httpd/access_log|sort -nr|uniq -c
   4004 192.168.27.6
 159091 172.18.56.3
     24 172.18.0.100

real    0m0.482s
user    0m0.444s
sys     0m0.036s

使用awk的效率可是相当高的呢

#time awk ‘{ ip[$1]++ }END{ for(i in ip){print ip[i],i} }‘ /var/log/httpd/access_log 
4004    192.168.27.6
24      172.18.0.100
159091  172.18.56.3

real    0m0.058s
user    0m0.055s
sys     0m0.002s

统计系统中使用每种bash的账号

#awk -F: ‘{ count[$NF]++ } END { for(i in count){ print count[i] ,i } }‘ /etc/passwd
1 /bin/sync
5 /bin/bash
16 /sbin/nologin
1 /sbin/halt
1 /sbin/shutdown

awk内置函数

rand 和 srand

rand()函数: 随机产生一个0到1之间的保留小数点后6位的小数值

#awk ‘BEGIN{rand();print rand()}‘
0.291066

srand()函数: 采用当前时间作为随机计数器的种子,这样以秒为间隔,随机数就能滚动随机生成了

awk ‘BEGIN{srand();print srand()}‘
1519348286

srand 和 rand 应该组合使用,以便rand()能够产生随机数值

#awk ‘BEGIN{srand();print rand()}‘
0.0114214

#awk ‘BEGIN{srand();print rand()}‘
0.0296973

int

作用: 截取整数部分的值(不是四舍五入)

#awk ‘BEGIN{srand();print int(rand()*100)}‘
32

#awk ‘BEGIN{srand();print int(rand()*100)}‘
18

length()

作用:返回指定字符串的长度

length函数可以省略传入的参数,当省略参数时,默认使用"$0"作为参数

#awk ‘BEGIN{var="ABCDEFG";print length(var)}‘
7

#awk -F: ‘{print $1,length($1)}‘ /etc/passwd
root 4
bin 3
daemon 6

sub(r,s,[t])

作用:对t字符串进行在指定范围内r 查找匹配的内容,并将第一个匹配的内容替换为s 。类似于sed中的s/A/B/

#echo "2018-2-23"|awk ‘sub(/-/,":",$0)‘
2018:2-23

gsub(r,s,[t])

作用:对t字符串进行在指定范围内r 查找匹配的内容,并将匹配的内容全部替换为s 。类似于sed中的s/A/B/g 全局替换

#echo "2018-2-23"|awk ‘gsub(/-/,":",$0)‘
2018:2:23

index(r,[t])

作用:对t字符串进行在指定范围内r 查找匹配的内容,如果匹配的内容存在于当前行,则返回字符串位于当前行的位置。如果没有匹配的内容,将返回0

#awk ‘{print index($0,"3"),$0}‘ 1.txt 
0 line 1
6 line 3    > 3存在于本行,且位于本行的第6个字符
0 line 2
6 line 3    > 3存在于本行,且位于本行的第6个字符
6 line 3    > 3存在于本行,且位于本行的第6个字符
0 line 4
0 line 5
0 line 5    > 不存在匹配的内容,返回0

split(s,array,[r])

作用:以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…从而动态的创建数组

#echo "2018-2-23"|awk ‘{ split($1,arr,"-") } END { for(i in arr) {print arr[i]} }‘
2018
2
23

被split函数分割后的数组的元素下标从1开始

#echo "2018-2-23"|awk ‘{ split($1,arr,"-") } END { print arr[0] }‘

#echo "2018-2-23"|awk ‘{ split($1,arr,"-") } END { print arr[1] }‘
2018
#echo "2018-2-23"|awk ‘{ split($1,arr,"-") } END { print arr[2] }‘
2

split函数默认返回值就是分割以后的数组元素个数

#echo "2018-2-23"|awk ‘{ arrleng=split($1,arr,"-") } END { print arrleng }‘
3

[[email protected] ~]#echo "2018-2-23-5"|awk ‘{ var=split($1,arr,"-") } END { print var }‘
4

system 函数

作用:调用Linux系统命令

注意:

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

#awk ‘BEGIN{system("uname -r")}‘        > 系统命令记得要用双引号引用
3.10.0-693.el7.x86_64
#awk ‘BEGIN{var="abcd";system("echo空格"var)}‘     > 使用system函数引用awk变量的时候,需要把变量名写在双引号外面,而且那个空格是必须的
abcd

awk 自定义函数

语法:

function 函数名 ( 形参1, 形参2, ... ) {
语句块
return 返回变量名
}
例子:

function max(v1,v2){
        v1>v2?var=v1:var=v2
        return var
}
BEGIN{print max(a,b)}   > 这里的是实参,必须要与形参格式一一对应。并且这一行就是awk后面跟的命令参数

如果以下行写死的情况下,是不需要在调用的时候awk -v指定实参的
BEGIN{a=3;b=10;print max(a,b)} >

调用方式:

#awk -v a=30 -v b=20 -f fun.awk 
30

编写自定义函数的时候,建议后缀名为.awk

在bash脚本中调用awk脚本的方法

#!/bin/awk -f          > 仅仅把bash脚本首行修改为这一行

执行的时候,记得不能以bash来执行哦

#chmod +x fun.awk
./fun.awk -v a=30 -v b=20

实例:

统计实时链接的IP

#netstat -tan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp        0     52 192.168.5.101:22        192.168.5.1:53134       ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 ::1:25                  :::*                    LISTEN
#netstat -tan | awk ‘/^tcp\>/{split($5,ip,":");count[ip[1]]++} END {for (i in count) {print i,count[i]} }‘

192.168.5.1 1
0.0.0.0 2

统计文件中每个单词的次数

root:x:0:0:root:/root:/bin/bash

#awk -F: ‘/^root/{ for(i=1;i<=NF;i++i){word[$i]++} } END { for(i in word){print "出现次数:"word[i],"字符:"i} }‘ /etc/passwd
出现次数:1 字符:/bin/bash
出现次数:1 字符:x
出现次数:1 字符:/root
出现次数:2 字符:0
出现次数:2 字符:root

按顺序遍历awk数组元素

#awk -v ts="aa-bb-11-22" ‘BEGIN{split(ts,arr,"-");for( i in arr){print i,arr[i]}}‘
4 22
1 aa
2 bb
3 11

使用for循环来遍历并且按顺序列出
#awk -v ts="aa-bb-11-22" ‘BEGIN{var=split(ts,arr,"-");for(i=1;i<=var;i++){print i,arr[i]}}‘
1 aa
2 bb
3 11
4 22

计算平均分

#cat file.txt 
张三 男 85
李四 男 96
赵云 女    99
梦回 女 100
王者 男 74

#awk ‘{if($2=="男"){inum++;isum+=$3}else{ynum++;ysum+=$3}}END{printf "男:%.2f\n女:%.2f\n",isum/inum,ysum/ynum}‘ file.txt 
男:85.00
女:99.50

用数组功能实现
#awk ‘{num[$2]++;sum[$2]+=$3}END{for(sex in num){print sex,num[sex],sum[sex]/num[sex]}}‘ file.txt 
男 3 85
女 2 99.5

将当前并发连接数大于某次数的IP添加至iptables拒绝列表中

ss -nt|awk -F "[ :]+" ‘/^ESTAB/{IP[$(NF-2)]++}END{for (i in IP){if (IP[i] >=1){system("iptables -A INPUT -s "i" -j REJECT")} }}‘

提取字符串中的数字

#echo ‘[email protected]%9&Bdh7dq+YVixp3vpw‘|awk ‘split($0,arr,""){for (i in arr){if (arr[i] ~ /[0-9]/){printf arr[i]}}}‘
37059

#echo ‘[email protected]%9&Bdh7dq+YVixp3vpw‘|awk -F "" ‘{for(i=1;i<=NF;i++){if ($i ~ /[0-9]/){ str=$i;str1=(str1 str) }} print str1}‘  
05973

备注:
str1=str1=(str1 str)每次str1存的就是上一次的值,括号内的空格是字符串连接。

运用此方法,可以拓展到一些其他的功能,比如提取大小写的英文字母或者是一些特殊的符号。只需要更改[0-9]这个条件。

[a-zA-Z]        提取大小写英文字符
[^0-9a-zA-Z]    提取除了数字,大小写英文以外的字符

以上是关于AWK ( 二 )的主要内容,如果未能解决你的问题,请参考以下文章

awk命令详解二

awk(二) 输出/删除指定列

Linux awk 命令详解(二) if 分支 数组

二.AWK内置变量

如何计算bash中一列数据中的连续重复次数?

Alfred常见使用