svn命令使用详解_awk命令使用详解

点击上方 “小白程序之路”,选择 “置顶公众号”

     更多资讯,第一时间送达!

介绍

AWK是一种处理文本文件的语言,是一个强大的文本分析工具,之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

语法
  • 第一种形式

$ awk 'BEGIN{}pattern{commands}END{}' file

  • 第二种形式

$ standard output | 'BEGIN{}pattern{commands}END{}'

工作原理

3abeca054d60105d5e656727fb011b62.png

其中数字1,2,3…代表是文本中的数据行

BEGIN{} 表示在处理文本数据之前进行一些操作

pattern{commands} 表示从文本中的第一行开始匹配满足pattern规则的行,执行commands命令,直到文本最后一行

END{} 表示在处理文本数据之后进行一些操作

内建变量
内置变量含义
$0整行内容
$1-$n当前行的第1-n个字段
NF当前行的字段个数,也就是有多少列
NR当前的行号,从1开始计数
FNR各文件分别计数的行号
FS字段分隔符(默认以空格或tab键分割)
RS输入行分隔符。默认回车换行
OFS输出字段分隔符。默认为空格
ORS输出行分隔符。默认为回车换行
FILENAME当前文件名

内置变量如何使用,我们以文本score.txt内容来做演示

$ cat  score.txt

marry 90  49  23  14

join  44  55  66  24

smile 55  78  80  34

jack  20  51  66  44

使用 $0来打印输出文件的每一整行的内容

$ awk '{print $0}' score.txt

marry 90  49  23  14

join  44  55  66  24

smile 55  78  80  34

jack  20  51  66  44

注意:行匹配语句 awk ' ' 只能用单引号

使用 $1$3来打印输出文件的的每一行第1列和第3列内容

$ awk '{print $1,$3}' score.txt

marry 49

join 55

smile 78

jack 51

使用 NF来输出每一行的列数

$ awk  '{print NF}' score.txt

5

5

5

5

使用awk没有指定分隔符,默认是以空格或者tab键来作分隔,在score.txt 文件中,经过分隔,每行都有5列

使用变量 $NF来输出文件

$ awk '{print $NF}' score.txt

14

24

34

44

从输出结果我们总结出,$NF就表示每一行的最后一列,因为文件中每一行有5列,则 $NF = $5

之前我们打印每一行的第1列和第3列我们使用的是:$1,$3;那么现在我们也可以使用:$(NF-2)$(NF-4)

$ awk '{print $(NF-4),$(NF-2)}' score.txt

marry 49

join 55

smile 78

jack 51

使用 NR来输出每一行的行号,这次我们把每一行的内容也打印出来

$ awk '{print NR "\t" $0}' score.txt

1    marry 90  49  23  85

2    join  44  55  66  22

3    smile 55  78  80  24

4    jack  20  51  66  89

使用 ORS来指定输出每一行的指定的分隔符

$ awk 'BEGIN{ORS="---"} {print $1,$NF}' score.txt

marry 14---join 24---smile 34---jack 44---

指定了每一行的分隔符为"---",现在输出的每一行都用---做分隔,而不在是默认的回车换行做分隔

使用 ORS指定了行的分隔符为"---",但是现在我们看到每一行输出的分隔符还是默认的空格来做分隔,比如:输出第一行的 marry14,现在我们使用 OFS来指定输出字段的分隔符,比如: *

$ awk 'BEGIN{ORS="---";OFS="*"} {print $1,$NF}' score.txt

marry*14---join*24---smile*34---jack*44---

使用 FS指定每一行的字段分隔符

$ awk 'BEGIN{FS=":"} {print $1,$NF}' /etc/passwd

root /bin/bash

bin /sbin/nologin

也可以使用这种形式指定分隔符(-F的意思就是指定分隔符)

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

如果指定多个分隔符,使用中括号 []包起来,里面指定具体的分隔符

$ awk -F '[-:]'

使用 FILENAME在处理多文件时候,可以打印出当前的文件名

$ awk 'BEGIN{FS="[ :]"} {print FILENAME "\t" $1,$NF}' score.txt  /etc/passwd

score.txt    marry 14

score.txt    join 24

score.txt    smile 34

score.txt    jack 44

/etc/passwd    root /bin/bash

/etc/passwd    bin /sbin/nologin

使用重定向拆分文件

准备文件 netstat.txt

$ cat netstat.txt

Proto Recv-Q Send-Q Local-Address           Foreign-Address         State

tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN

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      0 192.168.10.10:22        192.168.10.1:65016      ESTABLISHED

tcp        0      0 192.168.10.10:22        192.168.10.1:57253      ESTABLISHED

tcp6       0      0 :::111                  :::*                    LISTEN

tcp6       0      0 :::22                   :::*                    LISTEN

tcp6       0      0 ::1:25                  :::*                    LISTEN

udp        0      0 0.0.0.0:1018            0.0.0.0:*               FIN_WAIT2

udp6       0      0 :::1018                 :::*                    FIN_WAIT2

udp6       0      0 :::111                  :::*                    ESTABLISHED

udp6       0      0 ::1:323                 :::*                    ESTABLISHED

以空格为分隔符,按照 $6(第6列)也就是 State列进行拆分文件 netstat.txt(其中NR!=1表示不处理表头)

$ awk 'NR!=1{print > $6}' netstat.txt

$ ls

ESTABLISHED  FIN_WAIT2  LISTEN  netstat.txt

$ cat ESTABLISHED

tcp        0      0 192.168.10.10:22        192.168.10.1:65016      ESTABLISHED

tcp        0      0 192.168.10.10:22        192.168.10.1:57253      ESTABLISHED

udp6       0      0 :::111                  :::*                    ESTABLISHED

udp6       0      0 ::1:323                 :::*                    ESTABLISHED

$ cat FIN_WAIT2

udp        0      0 0.0.0.0:1018            0.0.0.0:*               FIN_WAIT2

udp6       0      0 :::1018                 :::*                    FIN_WAIT2

$ cat  LISTEN

tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN

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

tcp6       0      0 :::111                  :::*                    LISTEN

tcp6       0      0 :::22                   :::*                    LISTEN

tcp6       0      0 ::1:25                  :::*                    LISTEN

{print>$6} 是按照第6列进行拆分,将所有列输出到文件中,我们也可以指定列输出到文件中

$ awk 'NR!=1{print $1,$4> $6}' netstat.txt

awk使用 printf格式化输出

printf 格式说明符

格式符含义
%s打印字符串
%d打印十进制数
%f打印一个浮点数
%x打印十六进制数
%o打印八进制数
%e打印数字的科学计数法形式
%c打印单个字符的ASCII码

printf 修饰符

修饰符含义
-左对齐
+右对齐
#8进制显示在前面加0,16进制显示在前面加0X

上面演示的案例,我们都是用 print来做输出(默认是输出每行内容,用回车键作为换行),现在我们使用 printf(默认没有加任何的输出分隔符)来进行格式化打印输出

使用 %s以字符串形式输出/etc/passwd文件中第一列

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

root

bin

daemon

...

使用 \n 来指定输出每行的的分隔符

使用 $s%f%d%x等多个格式符来输出

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

sshd 74.000000 74 4a

postfix 89.000000 89 59

chrony 998.000000 998 3e6

vagrant 1000.000000 1000 3e8

vboxadd 997.000000 997 3e5

使用了不同的格式符,输出了/etc/passwd文件中的$1,$3列,对于稍微有点强迫症患者的朋友来说,可以看出输出结果并不美观,比如:每列都没有对齐(向左或者向右),浮点数列没有控制指定个数的精度等,下面我们就来解决这个问题

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

sshd                 74.00              74                   4a

postfix              89.00              89                   59

chrony               998.00          998                  3e6

vagrant              1000.00          1000                 3e8

vboxadd              997.00          997                  3e5

我们可以在每个格式符的前面加上数字,比如:%20s,表示这一列占位20个字符

使用 %0.2f 来指定这一列输出的精度,保留2位小数

使用 -格式符,表示输出的结果向左对齐

关系运算符、布尔运算符和匹配正则表达式
运算符含义
、 >=、 != 、 ==小于、小于等于...(关系运算符)
~匹配正则表达式
~!不匹配正则表达式
\\
&&逻辑与

匹配输出第一列字符等于 smile的行

$ awk '$1=="smile" {print $0}' score.txt

smile 55  78  80  34

匹配输出第一列字符等于 smile的行 ,或者第2列大于 80的行

$ awk '$1=="smile" || $2 > 80  {print $0}' score.txt

marry 90  49  23  14

smile 55  78  80  34

使用正则,匹配输出包含 44的行

$ awk '/44/ {print $0}' score.txt

join  44  55  66  24

jack  20  51  66  44

使用正则,匹配输出不包含 44的行

$ awk '!/44/ {print $0}' score.txt

marry 90  49  23  14

smile 55  78  80  34

使用正则,匹配输出以 join字符开头的行到以 jack字符开头结束的行

$ awk '/^join/,/^jack/ {print $0}' score.txt

join  44  55  66  24

smile 55  78  80  34

jack  20  51  66  44

使用正则,匹配第1列字符包含 jack并且最后一列大于等于 34

$ awk '$1 ~ /jack/ &&  $NF >= 34 {print $0}' score.txt

jack  20  51  66  44

~ 表示模式开始;/ / 中表示的是匹配的具体模式

现在看下正则模式取反的示例

$ awk '$1 !~ /jack/ &&  $NF >= 24 {print $0}' score.txt

join  44  55  66  24

smile 55  78  80  34

!~ ,第1列不包含字符 jack 并且最后列的值大于等于 24

算术运算符
运算符含义
+ 、 -加、减
* 、/ 、 %乘、除、求于
++、--增加或减少,作为前缀或后缀,如(++x、x--)

我们先来看一下简单的加法和除法运算

$ awk 'BEGIN{

 num1=10;

 num2=20;

 printf "%d %0.2f\n", num1+num2,num1/num2

}'

30 0.50

awk 声明的变量可以在任何多个花括号脚本中使用

计算/etc/services中空白行的数量

$ awk '/^$/ {sum++} END{print sum}' /etc/services

17

字符串函数
函数名含义
length(str)计算字符串长度
index(str1,str2)在str1中查找str2的位置
tolower(str)转换为小写
toupper(str)转换为大写
substr(str,m,n)从str的第m个字符开始,截取m位
split(str,arr,fs)按fs切割字符,结果保存arr中
match(str,RE)在str中按照RE查找

由于字符串函数是我们工作中常用的函数,比较简单,下面我们使用 split()函数来做演示

$ awk 'BEGIN{

 str="java#python#go";

 split(str,arr,"#");

 for(item in arr){

   print arr[item]

 }

}'

java

python

go

其中我们使用了for循环来遍历 arr 数组,下面我们会讲到

awk动作中使用条件及循环语句(可见awk是个脚本解释器)

条件表达式

  • if语句

语法格式如下:

if(条件){

   动作

}

示例:

$ awk -F: '{if($3>100 && $3<1000) print $0}' /etc/passwd

  • if - else 语句

语法格式如下:

if(条件){

   动作

}else{

   动作

}

示例:

$ awk 'BEGIN {

   num = 11;

   if (num % 2 == 0) {

     printf "%d 是偶数\n", num

   }else {

     printf "%d 是奇数\n", num

   }

}'

  • if - else - if 语句

语法格式如下:

if(条件){

   动作

}else if(条件){

   动作

}else{

   动作

}

示例:

$ awk  -F: '{

   if($3<100) {

     print  "系统用户", $1

   }

   else if($3>100 && $3 <900) {

     print  "普通用户", $1

   } else {

     print  "其它用户", $1

   }  

}'  /etc/passwd

循环语句

  • while 语句

while(条件){

   循环体

}

示例:

$ awk 'BEGIN {i=1; while(i<6){ print i; ++i } }'

  • do - while语句

语法格式:

do{

   循环体

}while(条件)

示例:

awk 'BEGIN{i=1;do{print i;i++}while(i<6)}'

  • for 语句

语法格式:

for(变量;条件;表达式){

   动作

}

示例:

$ awk 'BEGIN{

 sum=0;

 for(i=1;i<=100;i++){

   sum+=i

 }

 print sum

}'

常用选项
选项含义
-v参数传递
-V查看awk的版本号
-f指定脚本文件
-F指定分隔符

使用 -v引入外部变量

$ a=1

$ b="spring is framework"

$ awk -v c="$a" -v d="$b" 'BEGIN{print c , d}'

把awk的执行动作写在脚本中,使用 -f指定脚本文件

$ vim print.awk

$ BEGIN{print c , d}

执行脚本文件: print.awk

awk -v c="$a" -v d="$b" -f print.awk

使用 -F指定分隔符

我们之前可以使用内置变量 FS来指定分隔符,比如:

$ awk 'BEGIN{FS=":"} {print $1}' /etc/passwd

现在等价于:

$ awk -F ":" '{print $1}'  /etc/passwd

# 或者

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

b4d300ab6711cdd0c7e9ee5ee20dbf6f.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值