文本处理工具

文本处理小工具

tr

tr [选项]…SET1 [SET2]

从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出。

​ -c:取字符集的补集

​ -d:删除所有属于第一字符集的字符

​ -s:把连续重复的字符以单独一个字符表示(压缩)

​ -t:将第一个字符集对应字符转化为第二字符集对应的字符

#echo 'tank zhang' |tr a-z A-Z
TANK ZHANG
#cat > aaa.txt
aaa

bbb

#cat aaa.txt|tr 'a' 'c'
ccc

bbb

#cat aaa.txt|tr -d 'a'

bbb

#cat aaa.txt|tr -s '\n'
aaa
bbb

cut

cut – 在文件的每一行中提取片断

在每个文件 FILE 的各行中, 把提取的片断显示在标准输出.

​ -d:指定分割符

​ -f:指定打印的段落

sort

串联排序所有指定文件并将结果写到标准输出。

​ -n:按大小进行排序 -r:倒序 -k:按那一个字段进行排序 sort -t: -k3 -n /etc/passwd #按照第三列数字大小正序排列 sort -t: -k3 -nr /etc/passwd #按照第三列数字大小逆序排列 seq 102 |sort -R |head -n1 cut -d: -f1,3 /etc/passwd |sort -t: -k2 -nr

uniq

从输入文件或者标准输入中筛选相邻的匹配行并写入到输出文件或标准输出。

​ -c:统计重复个数,并打印重复个数

​ diff:文件不同点对比

​ patch:给文件打补丁 patch -p1 FILE1 < FILE2 //使用FILE1给FILE2进行打补丁

提取前10位访问量的用户IP
答案:cat /var/log/httpd/access_log |cut -d " " -f1 |sort |uniq -c \sort -nr |head -n10
统计远程主机登陆的前三名
答案:#last | tr -s " " ":"|cut -d: -f3|tr -d "[:alpha:]"|sort -nr|uniq -c|head -n -3|sort -t" " -k1 -nr

练习:
1、找出ifconfig “网卡名” 命令结果中本机的IPv4地址
答案:CentOS6:ifconfig  eth0 |head -n2|tail -n1|tr -s " "|cut -d: -f4
答案:CentOS7:ifconfig ens33|head -n2|tail -n1|tr -s " "|cut -d " " -f3
2、查出分区空间使用率的最大百分比值
答案:df |tr -s " " %|cut -d% -f5 |sort -nr |head -n1
3、查出用户UID最大值的用户名、UID及shell类型
答案:#cat /etc/passwd|cut -d: -f1,3,7|sort -t: -k2 -nr|head -n 1
4、查出/tmp的权限,以数字方式显示
答案:
5、统计当前连接本机的每个远程主机的连接数,并按从大到小排序
答案:#netstat -nt |tr -d "[:alpha:]()/-"|tr -s " " ":"|cut -d: -f6 |sort -nr|uniq -c|head -n -1|sort -t" " -k1 -nr

 

Linux文本处理三剑客

grep

grep的工作方式,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到屏幕,不影响原文件内容。

-E:使用扩展正则表达式 -R:不使用正则表达式 -v:显示不被pattern匹配到的行 -o:仅显示匹配到的字符串 -i:忽略大小写 -n:显示匹配的行号 -c: 统计匹配的行数 -A n:打印匹配行的后几行 -B n:打印匹配行的前几行 -C n:打印匹配行的前后几行

-w:匹配整个单词

-xz:匹配整行

   取所有的IP地址:ifconfig ens33 |grep -o "[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}"
    取当前系统的IP地址:ifconfig ens33| grep -o "inet [0-9.]\+"|cut -d " " -f2
    显示系统的版本号:
    cat /etc/redhat-release |grep -o "[0-9]\+"|head -n1
    过滤空行:grep -v ”^[[:space:]]*$“ f1

   查出分区空间使用率的最大百分比值
    答案:df |grep "/dev/sd" |grep -o "[0-9]\{1,3\}%"|sort -nr|head -n1

练习:
9、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法) 
答案: grep -i "^s" /proc/meminfo
      grep "^[sS].*" /proc/meminfo
10、显示/etc/passwd文件中不以/bin/bash结尾的行
答案:cat /etc/passwd | grep -v "/bin/bash$"
11、显示用户rpc默认的shell程序
答案:cat /etc/passwd |grep "^rpc\>" |cut -d: -f7
12、找出/etc/passwd中的两位或三位数
答案:cat /etc/passwd | grep -wo "[[:digit:]]\{2,3\}"
13、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行
答案:cat /etc/grub2.cfg |grep "^[[:space:]].*[^[:space:]].*"
14、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
答案:netstat -tan |grep "LISTEN[[:space:]]*$"
15、显示CentOS7上所有系统用户的用户名和UID
答案:cat /etc/passwd | cut -d: -f1,3 | grep  ":[1-9][0-9]\{,2\}$"
16、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行
答案:cat /etc/passwd | grep "^\(.\+\):.*/\1$"
    或cat /etc/passwd | grep "^\(.*\):.*/\1$"
17、利用df和grep,取出磁盘各分区利用率,并从大到小排序
答案:df | grep “/dev/sd” | grep -o “[0-9]*%” | sort -nr
18、显示三个用户root、mage、wang的UID和默认shell
答案:cat /etc/passwd |grep -E "^(wang |mage|root)\>" |cut -d: -f1,,3,7
19、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
答案:cat /etc/rc.d/init.d/functions |grep "^[[:alpha:]_].*()"
20、使用egrep取出/etc/rc.d/init.d/functions中其基名
答案:echo /etc/rc.d/init.d/functions |egrep -o "[^/]*/?$"    
21、使用egrep取出上面路径的目录名 
答案:echo /etc/rc.d/init.d/functions |egrep -o "^/.*/" 
22、统计last命令中以root登录的每个主机地址登录次数
答案:last | egrep root | egrep -wo ”[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+“ | uniq -c | sort -nr
23、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255 
答案:egrep -o "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))"
24、显示ifconfig命令结果中所有IPv4地址
答案:ifconfig |egrep -o  "\<(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>"  
25、将此字符串:welcome to magedu linux 中的每个字符去重并排序,重复次数多的排到前面
答案:echo "welcome to magedu linux" |grep -o . |sort |uniq -c |sort -nr 
26、复制/etc/profile至/tmp/目录,用查找替换命令删除/tmp/profile文件中的行首的空白字符
答案:cp /etc/profile  /tmp/ |grep -o "^[:blank:].*"  |
27、复制/etc/rc.d/init.d/functions文件至/tmp目录,用查找替换命令为 /tmp/functions的每行开头为空白字符的行的行首添加一个#号
答案:# :%s/^[[:space:]]/#&/g ^[[:space:]] 为标准的正则表达式,匹配的是以空白开头的行
28、在vim中设置tab缩进为4个字符
答案:# set ts=4
29、复制/etc/rc.d/init.d/functions文件至/tmp目录,替换/tmp/functions文件中的/etc/sysconfig/init为/var/log
答案:cp /etc/rc.d/init.d/functions  /tmp
     %s@/etc/sysconfig/init@/var/log
30、删除/tmp/functions文件中所有以#开头,且#后面至少有一个空白字符的行的行首的#号
答案:%s/^# \+//g 注意+号前面的转义字符

sed

行编辑器,流处理器

sed之所以能以行为单位的编辑或修改文本,其原因在于它使用了两个空间:一个是活动的“模式空间(pattern space)”,另一个是起辅助作用的“保持空间(hold space)这2个空间的使用。

模式空间:可以想成工程里面的流水线,数据之间在它上面进行处理。 保持空间:可以想象成仓库,我们在进行数据处理的时候,作为数据的暂存区域。

正常情况下,如果不显示使用某些高级命令,保持空间不会使用到!

sed在正常情况下,将处理的行读入模式空间,脚本中的“sed command(sed命令)”就一条接着一条进行处理,直到脚本执行完毕。然后该行被输出,模式被清空;接着,在重复执行刚才的动作,文件中的新的一行被读入,直到文件处理完毕。

sed语法:sed [option]…’script’ inputfile…. sed常用选项 -n:不输出模式空间内容到屏幕,即不自动打印 -i.bak //备份原有文件FILE.bak -r:支持使用扩展正则表达式 -e:多点编辑 -f:/PATH/SCRIPT_FILE 从指定文件中读取编辑脚本 sed的编辑命令 d:删除指定行 p:打印模式空间的内容 a []text:在指定行之后追加文本,可以使用/n进行换行 sed ‘2,5a\ ===’ f1 #在第二行到第五行之后插入空格加等号 i []text:在指定的之前添加文本 sed -i.bak ‘/aliases/aalias p=poweroff’ .bashrc sed -i.bak ‘/aliases/aalias cdnet=”cd /etc/sysconfig/network-scrts/”‘ .bashrc c []text:替换指定行 w /PATH/SOMEFILE:将匹配的行保存在指定文件 r /PATH/SOMFILE:读取指定的文件到模式空间中的指定位置 =:为模式空间匹配的行打印行号 ! :模式空间中匹配行取反处理

​ s///:查找替换,指出使用其它分隔符,s@@@,s### g:全局替换 p:打印 w /PATH/TO/SOMEFILE:将替换成功的行保存在指定文件中

sed示例一:
sed ‘2p’ /etc/passwd
sed –n ‘2p’ /etc/passwd
sed –n ‘1,4p’ /etc/passwd
sed –n ‘/root/p’ /etc/passwd
sed –n ‘2,/root/p’ /etc/passwd 从2行开始 
sed -n ‘/^$/=’ file 显示空行行号
sed –n –e ‘/^$/p’ –e ‘/^$/=’ file
sed ‘/root/a\superman’ /etc/passwd行后 
sed ‘/root/i\superman’ /etc/passwd 行前 
sed ‘/root/c\superman’ /etc/passwd 代替行
sed ‘/^$/d’ file
sed ‘1,10d’ file
nl /etc/passwd | sed ‘2,5d’
nl /etc/passwd | sed ‘2a tea’
sed 's/test/mytest/g' example
sed –n ‘s/root/&superman/p’ /etc/passwd 单词后 
sed –n ‘s/root/superman&/p’ /etc/passwd 单词前 
sed -e ‘s/dog/cat/’ -e ‘s/hi/lo/’ pets
sed –i.bak ‘s/dog/cat/g’ pets
示例二:
sed 's/root/administrator/g'  /etc/passwd
sed -r 's/(root)/\1er/g'  /etc/passwd      #-r指扩展的正则表达式
sed -r 's/(root)/admin\1/g'  /etc/passwd
sed -r 's/(.*)/\1magedu/' /etc/passwd  
sed -r 's@/bin/bash$@/sbin/bash@' /etc/passwd
sed -r 's@/(/bin/bash)$@/s\1@' /etc/passwd
sed -r '/GRUB_CMDLINE_LINUX/s/(.*)"$/\1 xyz"/' /etc/default/grub
sed -r '/GRUB_CMDLINE_LINUX/s/(.*)"$/ xyz"/' /etc/default/grub
sed -r 's/(GRUB_CMDLINE_LINUX.*)"$/\1  xyz"/'  /etc/default/grub

ifconfig ens33|sed -n '2p' | sed  -r 's@.*inet(.*).*@\1@'  
ifconfig ens33|sed -n '2p' | sed  -r 's@(.*inet)(.*)(  net.*)@\2@' 
ifconfig ens33|sed -r '2!d:s@(.*inet)(.*)( net.*)@\2@'
ifconfig ens33|sed -n '2p' |sed 's/.*int //' |sed 's/ netmask.*//'
ifconfig ens33|sed -n '2p' |sed -e 's/.*inet //' -e 's/ netmask.*//'
去掉前面的注释:sed -e '/^#NameVirtual/s/#//' -e '/^<VirtualHost/,/^#^<\/VirtualHost/s/#//'  /etc/httpd/conf/httpd.conf
取目录名:echo "/etc/sysconfig/network/" |sed -r 's/(.*\/)([^/]+\/?$)/\1'
取基名:echo "/etc/sysconfig/network/" |sed -r 's/(.*\/)([^/]+\/?$)/\2/'

​ 高级编辑命令

​ P:打印模式空间开端至\n内容,并追加到默认输出之前 g:[address[,address]]g 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容清除。

​ G:[address[,address]]G 将hold space中的内容append到pattern space\n后。 h:[address[,address]]h 将pattern space中的内容拷贝到hold space中,原来的hold space里的内容被清除。 H:[address[,address]]H 将pattern space中的内容append到hold space\n后。 d:[address[,address]]d 删除pattern中的所有行,并读入下一新行到pattern中。 D:[address[,address]]D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环 x:交换保持空间和模式空间的内容。

sed示例三:
sed -n 'n;p' FILE      #打印偶数行 
sed '1!G;h;$!d' FILE       #倒叙显示 
sed 'N;D‘ FILE     #只留最后一行 
sed '$!N;$!D' FILE     #只留下倒数两行 
sed '$!d' FILE     #只留最后一行
sed ‘G’ FILE       #输出结果中间加空行 
sed ‘g’ FILE       #删除全部数据,但位置不变
sed ‘/^$/d;G’ FILE     #输出结果中间加空行 
sed 'n;d' FILE     #打印奇数行
sed -n '1!G;h;$p' FILE     #倒叙排列
1、删除centos7系统/etc/grub2.cfg文件中所有以空白开头的行行首的空白字符
sed 's/^\([[:space:]]\+\)\([^[:space:]]\+\)/\2/g' /etc/grub2.cfg 

2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
sed 's/^\(#[[:space:]]\+\)\([^[:space:]]\+\)/\2/g' /etc/fstab 

3、在centos6系统/root/install.log每一行行首增加#号
sed 's/.*/#&/g' /root/install.log

4、在/etc/fstab文件中不以#开头的行的行首增加#号
sed 's/^[^#].*/#&/g' /etc/fstab

5、处理/etc/fstab路径,使用sed命令取出其目录名和基名
echo /etc/fstab|sed 's@\(^[/].*[/]\)\([^/]\+[/]\?\)@\1@g'
echo /etc/fstab|sed 's@\(^[/].*[/]\)\([^/]\+[/]\?\)@\2@g'

6、利用sed 取出ifconfig命令中本机的v4地址
ifconfig eth0|sed -n '2p'|sed 's/\(.*ddr:\)\(.*\)\(  Bcast.*\)/\2/g'
ifconfig eth0|sed -n '2p'|sed 's/.*ddr://g'|sed 's/  Bca.*//g'

7、统计centos安装光盘中Package目录下的所有rpm文件的以.分隔倒数第二个字段的重复次数
ls |sed -r 's/(.*[.])([^.]+)([.][^.]+)/\2/g'

8、统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现)
sed 's/[[:punct:]]/ /g' /etc/init.d/functions |tr '\t' ' '|tr ' ' '\n'|sed '/^$/d'|sort|uniq -c|sort -nr

9、将文本文件的n和n+1行合并为一行,n为奇数行
sed 'N;s/\n/\t /g' FILE

awk

awk变量,awk格式化,awk操作符,awk条件判断,awk循环,awk数组,awk函数,调用系统命令

报告生成器,格式化文本输出

awk相较于sed常常作用于整行的处理,awk比较倾向于一行当中分成数个字段来处理。awk相当适合处理小型的数据。在awk语法中行row,也可以称为记录record;列column,也可以称为字段fields、域area、属性Attributes。基本语法: awk [option] ‘program’ var=value file… awk [option] -f progarmfile var=value file… awk [option] ‘BEGIN{action;…}pattern{action;…}END{action;…}’file

program通常是被单引号或双引号中,一般用单引号。默认的字段分隔符为“空格键”或“【tab】键”选项 -F:指明输入时用到的字段分隔符 -v 进入变量模式 可以进行变量的赋值及调用(调用不需要加$符) 基本格式:awk [options]’program’file…program:pattern{action statements;…}pattern和action pattern部分决定动作语句何时触发及触发事件 BEGIN,END action statements对数据进行处理,放在{}内指明 print,printf分隔符、域和记录

awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称为域标识。$0为所有域,和shell中变量$符含义不同,如果省略action,则默认执行print $0操作。
示例:
awk '{print "hello,awk"}'
awk -F: '{print}' /etc/passwd
awk -F: '{print "root" }' /etc/passwd
awk -F: '{print $1}' /etc/passwd
awk -F: '{print $0}' /etc/passwd
awk -F: '{print $1" \t" $3}' /etc/passwd

awk变量:内置和自定义变量

    FS(field separate):输入字段分隔符,默认为空白字符
        awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
        awk -F: '{print $1,$3,$7}' /etc/passwd
    OFS:输出字段分隔符,默认为空白字符
        awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd
    RS(record separate):输入记录分隔符,指定输入时的换行符
        awk -v RS='' '{print}' /etc/passwd
    ORS:输出记录分隔符,输出时用指定符号代替换行符
        awk -v RS='' -v ORS='###' '{print}' /etc/passwd
    NF(number field):每一行($0)拥有的字段总数
        awk -F: '{print NF}' /etc/passwd
        awk -F: '{print $(NF-1)} /etc/passwd
    NR:目前awk所处理的是第几行的数据,即记录号
        awk '{print NR}' /etc/fstab;awk END'{print NR}' /etc/passwd
    FNR(filename number record):各文件分别计数,记录号
        awk '{print FNR}' /etc/fstab /etc/inittab
    FILENAME:当前文件名
        awk '{print FILENAME}' /etc/fstab
    ARGC:命令行参数的个数
        awk '{print ARGC}' /etc/fstab /etc/inittab
    ARGV:数组,保存的是命令行所给定的各参数
        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}'
    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

printf命令

格式化输出:printf “FORMAT”,item1,item2 …

(1)必须指定FORMAT

(2)不会自动换行,需要显示给出换行控制符

(3)FORMAT中需要分别为后面的每个item指定格式符

格式符:

​ %c:显示字符的ASCII码

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

​ %e,%E显示科学记数法数值

​ %f:显示为浮点数

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

​ %s:显示字符串

​ %u:无符号整数

​ %%:显示%自身

修饰符:

        # [.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
        -:左对齐(默认右对齐)%-15s
        +:显示数值的正负符号%+d

printf示例:

        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

​ 操作符

​ 算术操作符:

​ x+y,x-y, x*y, x/y, x^y, x%y

​ -x:转换为负数

​ +x:转换为数值

​ 赋值操作符:

​ =,+=,-=,*=,/=,%=,^ =

​ ++,–

​ 下面两语句有何不同

awk ‘BEGIN{i=0;print ++i,i}’

awk ‘BEGIN{i=0;print i++,i}’

​ 比较操作符:

​ == , != , > , >= , < , <=

​ 模式匹配符:

~左边是否和右边匹配含!~:是否不匹配

        示例:
        awk -F: '$0 ~ /root/{$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

​ 函数调用:

function_name(argu1,argu2,…)

​ 条件表达式(三目表达式)

    selector?if-true-expression:if-false-expression
示例:
awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd

​ awk PATTERN

​ PATTERN:根据pattern 条件,过滤匹配的行,再做处理

​ (1)如果未指定:空模式,匹配每一行

​ (2)/regular expression/:仅处理能够模式匹配到的行,需要用/ /扩起来

(3)relational expression:关系表达式,结果为“真”才会被处理

​ 真:结果为非0值,非空字符串

​ 假:结果为空字符串或0值

        示例:
        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

(4)line ranges:行范围

​ startline,endline:/pat1/,/pat2/不支持直接给出数字格式

             awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd
             awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

​ (5)BEGIN/END模式

​ BEGIN/END{}:仅在开始处理文件中的文本之前执行一次

​ END{}:仅在文本处理完成之后执行一次

示例:
awk -F : 'BEGIN {print "USER USERID"} {print $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 UID \n--------------- "}{print $1,$3}'END{print "=============="} /etc/passwd
seq 10 |awk ‘i=0’   #等同于seq 10 |awk 'i=0{print $0},0为假,所以输出结果为空
seq 10 |awk ‘i=1’   #输出结果为1到10
seq 10 | awk 'i=!i‘ #打印奇数行
seq 10 | awk '{i=!i;print i}‘   #打印1010101010
seq 10 | awk ‘!(i=!i)’  #打印偶数行
seq 10 |awk -v i=1 'i=!i'   #打印偶数行

awk action

常用的action分类

(1)Expressions:算术,比较表达式等

(2)Control statements:if ,while等

(3)compound statements:组合语句

(4)input statements

(5)output statements:print等

awk控制语句if-else

语法: if(condition){statement;…}[else statement]

if(condition1){statement1}else if(condition2){statement2}else{statement3}

使用场景:对awk取得的整行或某个字段做条件判断

示例:
awk -F:'{if($3>=1000)print $1,$3}'  /etc/passwd
awk -F:'{if($NF=="/bin/bash")print $1}' /etc/passwd
awk -F:'{if(NF>5)print$0}' /etc/fstab
awk -F:'{if($3>=1000){print"Common user:%s\n,$1}else{print"root or Sysuer:%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"}}'

awk控制语句

while循环

语法:while(condition){statement;…}

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

使用场景:

对一行内的多个字段逐一类似处理时使用

对数组中的各元素逐一处理时使用

示例:
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)};}}' /etc/grub2.cfg

do-while循环

语法:do {statement;…}while(condition)

意义:无论真假,至少执行一次循环体

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

for循环

语法:for(expr1;expr2;expr3){statement;…}

常见用法:

for(variable assignment;condition;iteration process)

{for-body}

特殊用法:能够遍历数组中的元素

语法:for(var in array){for-body}

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

awk控制语句

switch语句

语法:switch(expression){case VALUE1 or /REGEXP/:statement1;case VALUE2 or /REGEXP2/:statemet2/:statement2;…;default:statement}

break和continue

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控制语句

break[n]

continue[n]

Next:

提前结束对本行处理而直接进入下一行处理(awk自身循环)

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

awk数组

关联数组:array[index-expression]

Index-expression:

cat > test1.txt
1,beijing
1,beijing
2,beijing
3,tianjin
5,tianjin
15,shanghai
# awk -F"," '{ary[$2]+=$1} END{for(key in ary)print ary[key]","key}'
4,beijing
8,tianjing
15,shanghai

(1):可使用任意字符串;字符串要使用双括号括起来

(2):如果某数组元素事先不存在,在使用时,awk会自动创建次元素,并将其值初始化为“空串”

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

示例:
weekdays[ "mon" ]="Monday"
awk 'BEGIN{weekdays["mon"]="Mondya";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
awk '!arr[$0]++ dupfile

若要遍历数组中的每个元素,要使用for循环

for(var in array){for-body}

注意:var会遍历array的每个索引

示例:
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesdya";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

awk函数

数值处理:

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

Awk ‘BEGIN{srand();for(i=1;i<=10;i++)print int(rand()*100)}’

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

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

echo “2008:08:08 08:08:08” |awk ‘sub(/:/, “-,$1”)’

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

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

split(s,starry,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…

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

awk函数

自定义函数

格式: function name(parameter, parameter,…){

statements

return expression

}

示例:
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

awk中调用shell命令

system命令

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

awk BEGIN'{system(“hostname”)}’

awk ‘BEGIN{score=100;system(“echo your score is” score)}’

awk脚本

将awk程序写成脚本,直接调用或执行

示例:
cat f1.awk
    {if($3>=1000)print $1,$3}
awk -F:-f f1.awk  /etc/passwd

cat f2.awk
    # f2.awk -f
    #this is a awk script
    {if($3>=1000)print $1,$3}
chmod +x f2.awk
f2.awk -F:  /etc/passwd

向awk脚本传递参数

格式:

awkfile var=value var2=value2…inputfile

注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v参数,让awk在执行BEGIN之前得到变量的值。命令行只能够每一个指定的变量都需要一个-v参数

示例:
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

统计row中某个字段出现的次数

1、统计本机被访问次数

Awk ‘/^[0-9]/{ip{$1}++}END{for(i in ip){print i ,ip[i]}}’ /var/log/httpd/access_log

2、如果超过访问超过1000次就视为攻击,放入防火墙中

for i in `awk

iptables -A INPUT -s 192.168.30.6 -j REJECT

3、抽取连接本机ip的前十位。

4、统计/etc/rc.sysinit某个文档里面某个单词出现的次数,默认以空格位分隔符

思路:逐行统计,再汇总

5、某班考试成绩表如下:

姓名 性别 成绩
mage male 100
zhangsir male 99
bai female 90
li female 100

根据成绩表,统计男生平均成绩和女生平均成绩

#cat score.txt
mage        100     m
zhangsir    100     m
bai         90      f
li          100     f

方法1:
#   awk '{if($NF=="m"){sum_m+=$2;num_m++}else{sum_f+=$2;num_f++}}END{print "male:%.2f\nfemale:%.2f\n",sum_m/num_m,sum_f/num_f}' score.txt
male:99.50
female:95.00
方法2:数组
awk '{num[$NF]++;sum[$NF]+=$2}END{for(sex in num)printf "%s:%.2f\n",sex,sum[sex]/num[sex]}' score.txt
m:99.50
f:95.00

 

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/98029

发表评论

登录后才能评论

This site uses Akismet to reduce spam. Learn how your comment data is processed.

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班