awk如何指定多分隔符

awk的-F参数可以指定新的分隔符,有些时候可能需求指定多个分隔符,比如下面的内容

[root@N1 ~]# netstat -an | grep ESTAB 
udp        0      0 192.168.1.120:35570     212.47.249.141:123      ESTABLISHED
udp        0      0 192.168.1.120:55589     108.59.2.24:123         ESTABLISHED

如果需要取出源IP的话,一般大家会这样做,即做两次awk操作

[root@N1 ~]# netstat -an | grep ESTAB | awk  '{print $5}' | awk -F: '{print $1}'
108.59.2.24
212.47.249.141

其实呢,通过在awk中指定两个分隔符(空格和:),即可一次性的提取出源IP地址,在awk中支持多个分隔符的写法如下:

[root@N1 ~]# netstat -an | grep ESTAB | awk -F '[ :]+' '{print $6}'
108.59.2.24
212.47.249.141
#多一个加号表明将连续出现的分隔符当做一个来处理

注意:

在awk中,当分隔符指定为空字符串时,awk会将多个连续的空白看做一个单一的分隔符。此外,awk还会忽略开头和结尾处的空白。

如何在bash中使用awk比较日期

问题

有一个文件每行包含了一些信息,其中一个字段是生日。我想打印在指定一个日期之后日期那些行。我使用如下awk命令:

awk -F '|' 'FNR>1 $dateA<=$5 {print $1" "$2" "$3" "$4" "$5" "$6" "$7" "$8}' $FILE

不过似乎不行(所有行都打印了)。日期格式为YYYY-MM-DD,所以字母顺序也按时间顺序排列。
这个文件其中的一些行:

1099511628908|Chen|Wei|female|1985-08-02|2010-05-24T20:52:26.582+0000|27.98.244.108|Firefox
1099511633435|Smith|Jack|male|1981-04-19|2010-05-26T03:45:11.772+0000|50.72.193.218|Internet Explorer
1099511635042|Kiss|Gyorgy|male|1984-09-14|2010-05-16T22:57:41.808+0000|91.137.244.86|Chrome
1099511635218|Law-Yone|Eric|male|1987-01-20|2010-05-26T20:10:22.515+0000|203.81.95.235|Chrome
1099511638444|Jasani|Chris|female|1981-05-22|2010-04-29T20:50:40.375+0000|196.223.11.62|Firefox
2199023256615|Arbelaez|Gustavo|male|1986-11-02|2010-07-17T18:53:47.633+0000|190.96.218.101|Chrome

最佳答案

其中的一种解决方法:

dateA='1985-01-01'
infile='file to read values from'
awk -F '|' -v dateA="$dateA" '{if (FNR>1 && dateA<=$5) {print}}' "$infile"

更简洁的方法:

awk 'FNR>1 && dateA<=$5' FS='|' dateA="$dateA" "$infile"

或者:

awk 'FNR>1 && "'"$dateA"'"<=$5' FS='|' "$infile"

使用sed或awk显示指定行内容

文件内容为

[root@test1 test]# cat file.test
1
2
3
4
5
6
7
8
9
10

1. 显示第二行内容(指定行)

  • sed
[root@test1 test]# sed -n '2p' file.test
2
  • awk
[root@test1 test]# awk 'NR==2 {print $0}' file.test
2
[root@test1 test]# awk '{if(NR==2)print $0}' file.test
2

2. 显示第三行至第五行内容(指定行范围)

  • sed
[root@test1 test]# sed -n '3,5p' file.test
3
4
5
  • awk
[root@test1 test]# awk '{if(NR>2&&NR<6) print $0}' file.test
3
4
5
  • grep
[root@test1 test]# grep -C 1 4 file.test
3
4
5

3. 显示奇数行与偶数行

  • sed
[root@test1 test]# sed -n '1~2p' file.test
1
3
5
7
9
[root@test1 test]# sed -n '2~2p' file.test
2
4
6
8
10
[root@test1 test]# sed -n 'p;n' file.test
1
3
5
7
9
[root@test1 test]# sed -n 'n;p' file.test
2
4
6
8
10
  • awk
[root@test1 test]# awk 'NR%2==1' file.test
1
3
5
7
9
[root@test1 test]# awk 'NR%2==0' file.test
2
4
6
8
10
[root@test1 test]# awk '{if(NR%2==1) print $0}' file.test
1
3
5
7
9
[root@test1 test]#
[root@test1 test]# awk '{if(NR%2==0) print $0}' file.test
2
4
6
8
10

4. 显示匹配到的行

  • sed
[root@test1 test]# sed -n '/5/p' file.test
5 line 5
  • awk
[root@test1 test]# awk '/5/' file.test
5 line 5
  • grep
[root@test1 test]# grep 5 file.test
5 line 5

用awk实现按列求和及求平均值

平常的统计中肯定需要用上对取出来的一列数据进行求和求平均值。使用awk很容易实现。具体演示的命令如下:

[root@123 build]# ll
total 336
-rw-rw-r-- 1 1000 1000   3330 Mar 14 21:17 ax_check_compile_flag.m4
-rw-rw-r-- 1 1000 1000   2200 Mar 14 21:17 build2.mk
-rwxrwxr-x 1 1000 1000   2165 Mar 14 21:17 buildcheck.sh
-rw-rw-r-- 1 1000 1000   2510 Mar 14 21:17 build.mk
-rwxrwxr-x 1 1000 1000    381 Mar 14 21:17 config-stubs
-rw-rw-r-- 1 1000 1000    700 Mar 14 21:17 genif.sh
-rw-rw-r-- 1 1000 1000 230377 Mar 14 21:17 libtool.m4
-rw-rw-r-- 1 1000 1000   2225 Mar 14 21:17 mkdep.awk
-rw-rw-r-- 1 1000 1000   1556 Mar 14 21:17 order_by_dep.awk
-rw-rw-r-- 1 1000 1000    122 Mar 14 21:17 print_include.awk
-rw-rw-r-- 1 1000 1000    410 Mar 14 21:17 scan_makefile_in.awk
-rwxrwxr-x 1 1000 1000  65761 Mar 14 21:17 shtool
[root@123 build]# ll | awk '{print $5}'
3330
2200
2165
2510
381
700
230377
2225
1556
122
410
65761
[root@123 build]# ll | awk '{a=a+$5;b++;}END{print a,b,a/b}'
311737 13 23979.8
[root@123 build]# ll | awk '/build/ {print $9,$5}'                  
build2.mk 2200
buildcheck.sh 2165
build.mk 2510
[root@123 build]# ll | awk '/build/ {a=a+$5;b++}END{print a,b,a/b}' 
6875 3 2291.67
[root@123 build]# 

Linux awk命令详解

awk :适用程序,一种unix工具

就是一个强大的文本分析工具,相对于grep查找、sed的编辑,awk在对数据分析并生成报告的时候,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种处理。

  • awk是用来操作数据和产生报表的一种编程语言。数据可能来自标准输入、一个或多个文件或一个进程的输出等。awk可以用在命令行里进行简单操作,也可应用到较大的应用程序中。
  • awk是一门编程语法,作为unix工具来使用简化了很多,但是仍然有许多编程语言的特性,可以对目标进行一系列的处理。

  • 如果抛出awk的BEGIN和END,对文件的每行,awk都分两个阶段处理:

1、读取该行内容,分配临时寄存器,分配域名等操作;
2、对域做各种处理并输出;

  • awk基本用途

1、简单输出,如 awk ‘{print 1,NF}’ — print的规则
2、作为分隔符使用

单字符分隔符:打印系统中用户名和其他使用shell类型
单字符分隔符,管道连续使用awk:打印nginx日志中的访问目录。
多字符分隔符:抓取apache详细版本
多字符多个分隔符:截取ip地址
正则分隔符:截取ip地址

[root@admin test]# ls -l
total 16
-rw-r--r--. 1 root root    0 Jun 15 11:03 aa.jpg
-rw-r--r--. 1 root root   12 Jun 15 10:48 ls.jpg
-rw-r--r--. 1 root root  200 Jun 15 11:31 result.jpg
-rw-r--r--. 1 root root    0 Jun 15 11:04 right.jpg
drwxr-xr-x. 2 root root 4096 Jun 20 06:39 sd.ex
-rw-r--r--. 1 root root   49 Jun 15 11:04 wrong.jpg

通过awk打印出第一列:

[root@admin test]# ls -l | awk '{print $1}'
total
-rw-r--r--.
-rw-r--r--.
-rw-r--r--.
-rw-r--r--.
drwxr-xr-x.
-rw-r--r--.

打印前两列,也就是前两个域:

[root@admin test]# ls -l | awk '{print $1,$2}'
total 16
-rw-r--r--. 1
-rw-r--r--. 1
-rw-r--r--. 1
-rw-r--r--. 1
drwxr-xr-x. 2
-rw-r--r--. 1

在awk中,抛开BEGIN和END不看,’{}’ 这是一个固定写法。

$ : 符号表示域,域之间通过默认的分隔符 空格 分开,如果有多个空格就会变成一个空格,第一个域为$1,第二个为$2等…

打印最后一列:

[root@admin test]# ls -l | awk '{print $NF}'
16
aa.jpg
ls.jpg
result.jpg
right.jpg
sd.ex
wrong.jpg

$NF : 就代表最后一列的意思。
如果想打印倒数第二列,则使用$(NF -1)。

[root@admin test]# ls -l | awk '{print $(NF - 1)}'
total
11:03
10:48
11:31
11:04
06:39
11:04

-F :参数-F是改变awk的默认分隔符,可以支持正则表达式。

[root@admin test]# ls -l
total 16
-rw-r--r--. 1 root root    0 Jun 15 11:03 aa.jpg
-rw-r--r--. 1 root root   12 Jun 15 10:48 ls.jpg
-rw-r--r--. 1 root root  200 Jun 15 11:31 result.jpg
-rw-r--r--. 1 root root    0 Jun 15 11:04 right.jpg
drwxr-xr-x. 2 root root 4096 Jun 20 06:39 sd.ex
-rw-r--r--. 1 root root   49 Jun 15 11:04 wrong.jpg

awk默认的分隔符是 空格,空格前一列就是$1,后面是$2,$3…..
当我们改变默认分隔符为 分号 “:”时,打印一下结果:

[root@admin test]# ls -l | awk -F":" '{print $NF}'
total 16
03 aa.jpg
48 ls.jpg
31 result.jpg
04 right.jpg
39 sd.ex
04 wrong.jpg

通过-F 参数改变默认分隔符,以及其支持正则表达式的特性,精确的抽出ifconfig 文件中的ip地址。

#精确的抽取ip地址
[root@admin test]# ifconfig | grep "inet addr" | awk -F "addr:|  *" '{print $4}'
192.168.1.6
127.0.0.1

分析:

grep "inet addr" 表示先抽取出含有ip的那行,然后通过管道交给awk去处理

-F "addr:|  *" :表示该变默认分隔符为addr:或者连续多个空格

$4 :表示改变默认分隔符以后,ip地址在第4个域。

用grep实现抽取ip :

[root@admin home]# ifconfig | egrep -o "[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*"
192.168.1.6
192.168.1.255
255.255.255.0
127.0.0.1
255.0.0.0

然后在用head和tail抽取想要的ip即可。

使用sed实现抽取ip

[root@admin home]# ifconfig |grep "inet addr" | sed 's/inet addr://' | sed 's/Bcast.*//' | head -1
192.168.1.6
或者:
[root@admin home]# ifconfig |grep "inet addr" | sed 's/^.*addr://;s/  *.*//' | head -1
192.168.1.6

awk匹配打印

注:需要匹配的内容是写在{}外面的,通过//来体现匹配。
匹配打印实际上是文件每行读取的时候做的处理。

1、整行中匹配内容

awk '/sth/{print $1}' ---打印匹配sth的行的第一个域,这是对整行进行操作
awk '!/sth/{print $1}'  ---打印不匹配sth的行的第一个域

如匹配打印sd关键字:

[root@admin test]# ls
aa.jpg  ls.jpg  result.jpg  right.jpg  sd.ex  wrong.jpg

[root@admin test]# ls | awk '/sd/{print $1}'
sd.ex

2、域匹配内容

匹配某个文件中以默认分隔符分隔的$1域中含有关键字sth的行,然后打印出第一个域,命令如下:

awk '$1~/sth/{print $1}' 

3、改变awk中的默认分隔符

如打印出passwd文件中,以冒号 : 分隔的第一个域中含有关键字wcx行的第一个域:

[root@admin etc]# cat passwd | awk -F":" '$1~/wcx/{print $1}'
wcx

awk判断打印

判断打印实际上是文件每行读取后做的处理。
格式例如:

awk '{if($1=="wcx")print $1}'

if 判断必须是进入某一行以后才能做的,所以必须是在花括号{} 里面。而模式匹配是先匹配到内容的行才能进行下一步操作,所以模式匹配实在花括号{}外边。

[root@admin etc]# cat ./passwd | awk -F ":" '{if($1 == "wcx")print}
wcx:x:501:501::/home/wcx:/bin/bash

上面命令中,如果passwd文件中,以冒号分隔的第一个域==”wcx”,那么就打印出来,这是等于判断,所以只有wcx的行能出来。

BEGIN和END

在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。
任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。

awk的数组

有一个awk.txt文件,其内容如下:

[root@admin home]# cat awk.txt
kk kekea
jj d32
jame 23
sr
sr
kk
jame
wcx
jame 

统计一下awk.txt文件中每个人名出现的次数:

[root@admin home]# cat awk.txt | awk '{a[$1]++}END{for (i in a)print i,a[i]}'
wcx 1
jj 1
kk 2
sr 2
jame 3

解题思路分析:

  • {a[$1]++} :awk开始扫描管道传过来的内容,但是么有存储功能,现在我们需要计算每个人名出现的额次数,所以需要把扫描到的相同的人名分别存储起来,这时候就必须用数组,并且这里的数组都是hash数组,就是键值对的数组,这里的键—对应的就是对应域中的人名,如kk,值 — 对应的就是kk这个人名出现的次数。数组a中的下标$1代表的是第一个域中列名,如wcx。awk开始逐行扫描,每扫到一个相同的人名,对应的hash数组里的值就+1,如a[kk]++,直到扫到文件的结尾。(注:数组的默认值为空,如果要做++操作了,就会把里的值变成0)

  • END : END之后列出的操作将在Unix awk开始扫描完全部的输入之后执行。上面扫描完以后,就开始执行END后面的操作了。

  • {for (i in a)print i,a[i]} :利用for循环去遍历刚刚产生的hash数组,然后打印出数组下标所代表的值,也就是人名以及对数组中的值,也就是对应人名出现的次数。这里的i,就代表数组的下标,也就是域中的人名,如kk。

awk输出分隔符

awk默认的输出分隔符也是空格,如果想改变默认输出分隔符怎么做?

[root@admin home]# cat awk.txt | awk '{print $1,$2}'
kk kekea
jj d32
jame 23
sr 234
sr edr
kk 23
jame rt
wcx 88
jame 34

运行结果看出,打印时,$1和$2间加了逗号以后,输出的文本中域间就都是用空格隔开的。

如果我不加逗号,改为加一串别的字符时,输出后就以加入的字符作为分隔符了。如:

[root@admin home]# cat awk.txt | awk '{print $1"--"$2"BB"}'
kk--kekeaBB
jj--d32BB
jame--23BB
sr--234BB
sr--edrBB
kk--23BB
jame--rtBB
wcx--88BB
jame--34BB

通过awk批量修改扩展名

[root@admin test]# ls
aa.jpg  ls.jpg  result.jpg  right.jpg  wrong.jpg

将test目录下的以.jpg结尾的文件改成.txt结尾的文件:

[root@admin test]# ls | awk -F "." '{print "mv "$1"."$2" "$1".txt"}'|sh
[root@admin test]# ls
aa.txt  ls.txt  result.txt  right.txt  wrong.txt

或者:
[root@admin test]# ls | awk -F "." '{print "mv "$0" "$1".txt"}' | sh
#$0表示整行的内容

思路分析,同样改名也是需要构造mv a.txt a.jpg这样类似的语句的,这就用到了上面讲的输出时修改默认分隔符的操作了。构造出的mv语句再传给sh去执行就可以实现改名的操作。

awk内置变量使用介绍

未分类

我们将逐渐揭开 awk 功能的神秘面纱,在本节中,我们将介绍 awk 内置built-in变量的概念。你可以在 awk 中使用两种类型的变量,它们是:用户自定义user-defined变量和内置变量。awk 内置变量已经有预先定义的值了,但我们也可以谨慎地修改这些值.

awk 内置变量包括

  • FILENAME : 当前输入文件名称
  • NR : 当前输入行编号(是指输入行 1,2,3……等)
  • NF : 当前输入行的字段编号
  • OFS : 输出字段分隔符
  • FS : 输入字段分隔符
  • ORS : 输出记录分隔符
  • RS : 输入记录分隔符

FILENAME

让我们继续演示一些使用上述 awk 内置变量的方法,想要读取当前输入文件的名称,你可以使用 FILENAME 内置变量,如下:

$ awk ' { print FILENAME } ' ~/domains.txt

未分类

你会看到,每一行都会对应输出一次文件名,那是你使用 FILENAME 内置变量时 awk 默认的行为。我们可以使用 NR 来统计一个输入文件的行数(记录),谨记:它也会计算空行,正如我们将要在下面的例子中看到的那样。 输出文件内容 当我们使用 cat 命令查看文件 domains.txt 时,会发现它有 14 行文本和 2 个空行:

$ cat ~/domains.txt

未分类

awk 统计行数

$ awk ' END { print "Number of records in file is: ", NR } ' ~/domains.txt

未分类

awk 统计文件中的字段数

$ awk '{ "Record:",NR,"has",NF,"fields" ; }' ~/names.txt

未分类

FS 内置变量

你也可以使用 FS 内置变量指定一个输入文件分隔符,它会定义 awk 如何将输入行划分成字段。FS 默认值为“空格”和“制表符”,但我们也能将 FS 值修改为任何字符来让 awk 根据情况切分输入行。有两种方法可以达到目的:第一种方法是使用 FS 内置变量;第二种方法是使用 awk 的 -F 选项。来看 Linux 系统上的 /etc/passwd 文件,该文件中的各字段是使用 冒号(:) 分隔的,因此,当我们想要过滤出某些字段时,可以将冒号(:) 指定为新的输入字段分隔符, awk 过滤密码文件中的各字段 . 我们可以使用 -F 选项,如下:

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

未分类

此外,我们也可以利用 FS 内置变量,如下:

$ awk ' BEGIN { FS=“:” ; } { print $1, $4 ; } ' /etc/passwd

未分类

使用 OFS 内置变量

使用 OFS 内置变量来指定一个用于输出的字段分隔符,它会定义如何使用指定的字符分隔输出字 段 使用 awk输出的分隔符:

$ awk -F':' ' BEGIN { OFS="==>" ;} { print $1, $4 ;}' /etc/passwd

未分类

在本节中,我们已经学习了使用含有预定义值的 awk 内置变量的理念。但我们也能够修改这些值,虽然并不推荐这样做,除非你明白自己在做什么,并且充分理解(这些变量值)。

linux awk命令使用详解

当你第一次拿起双手在电脑上使用 awk 命令处理一个或者多个文件的时候,它会依次读取文件的每一行内容, 然后对其进行处理,awk 命令默认从 stdio 标准输入获取文件内容, awk 使用一对单引号来表示 一些可执行的脚本代码,在可执行脚本代码里面,使用一对花括号来表示一段可执行代码块,可以同时存在多个代码块。 awk 的每个花括号内同时又可以有多个指令,每一个指令用分号分隔,awk 其实就是一个脚本编程语言。说了这么多,你肯定还是一脸的懵逼。先别急,往下看。。。

1、awk 命令的基本格式

awk [options] 'program' file

options 这个表示一些可选的参数选项,反正就是你爱用不用,不用可以拉到。。。 program 这个表示 awk 的可执行脚本代码,这个是必须要有的。 file 这个表示 awk 需要处理的文件,注意是纯文本文件,不是你的 mp3,也不是 mp4 啥的。。

2、先来一个 awk 的使用例子热热身

$ awk '{print $0}' /etc/passwd

awk 命令的可执行脚本代码使用单引号括起来,紧接着里面是一对花括号,记住是 “花括号” 不是 “花姑娘”,然后花括号里面就是一些可执行的脚本代码段,当 awk 每读取一行之后,它会依次执行双引号里面的每个脚本代码段,在上面这个例子中, $0 表示当前行。当你执行了上面的命令之后,它会依次将 /etc/passwd 文件的每一行内容打印输出。

3、awk 自定义分隔符

awk 默认的分割符为空格和制表符,我们可以使用 -F 参数来指定分隔符

$ awk -F ':' '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp
nobody

上面的命令将 /etc/passwd 文件中的每一行用冒号 : 分割成多个字段,然后用 print 将第 1 列字段的内容打印输出

4、如何在 awk 中同时指定多个分隔符

比如现在有这样一个文件 some.log 文件内容如下

Grape(100g)1980
raisins(500g)1990
plum(240g)1997
apricot(180g)2005
nectarine(200g)2008

现在我们想将上面的 some.log 文件中按照 “水果名称(重量)年份” 来进行分割

$ awk -F '[()]' '{print $1, $2, $3}' some.log
Grape 100g 1980
raisins 500g 1990
plum 240g 1997
apricot 180g 2005
nectarine 200g 2008

在 -F 参数中使用一对方括号来指定多个分隔符,awk 处理 some.log 文件时就会使用 “(” 和 “)” 来对文件的每一行进行分割。

5、awk 内置变量的使用

  • $0 这个表示文本处理时的当前行
  • $1 表示文本行被分隔后的第 1 个字段列
  • $2 表示文本行被分割后的第 2 个字段列
  • $3 表示文本行被分割后的第 3 个字段列
  • $n 表示文本行被分割后的第 n 个字段列
  • NR 表示文件中的行号,表示当前是第几行
  • NF 表示文件中的当前行列的个数,类似于 mysql 数据表里面每一条记录有多少个字段
  • FS 表示 awk 的输入分隔符,默认分隔符为空格和制表符,你可以对其进行自定义设置
  • OFS 表示 awk 的输出分隔符,默认为空格,你也可以对其进行自定义设置
  • FILENAME 表示当前文件的文件名称,如果同时处理多个文件,它也表示当前文件名称

比如我们有这么一个文本文件 fruit.txt 内容如下,我将用它来向你演示如何使用 awk 命令工具,顺便活跃一下此时尴尬的气氛。。

peach 100 Mar 1997 China
Lemon 150 Jan 1986 America
Pear 240 Mar 1990 Janpan
avocado 120 Feb 2008 china

我们来瞧一瞧下面这些简单到爆炸的例子,这个表示打印输出文件的每一整行的内容

$ awk '{print $0}' fruit.txt
peach 100 Mar 1997 China
Lemon 150 Jan 1986 America
Pear 240 Mar 1990 Janpan
avocado 120 Feb 2008 china

下面这个表示打印输出文件的每一行的第 1 列内容

$ awk '{print $1}' fruit.txt
peach
Lemon
Pear
avocado

下面面这个表示打印输出文件的每一行的第 1 列、第 2 列和第 3 列内容

$ awk '{print $1, $2, $3}' fruit.txt
peach 100 Mar
Lemon 150 Jan
Pear 240 Mar
avocado 120 Feb

其中加入的逗号表示插入输出分隔符,也就是默认的空格

文件的每一行的每一列的内容除了可以用 print 命令打印输出以外,还可以对其进行赋值

$ awk '{$2 = "***"; print $0}' fruit.txt
peach *** Mar 1997 China
Lemon *** Jan 1986 America
Pear *** Mar 1990 Janpan
avocado *** Feb 2008 china

上面的例子就是表示通过对 $2 变量进行重新赋值,来隐藏每一行的第 2 列内容,并且用星号 * 来代替其输出

在参数列表中加入一些字符串或者转义字符之类的东东

$ awk '{print $1 "t" $2 "t" $3}' fruit.txt
peach 100 Mar
Lemon 150 Jan
Pear 240 Mar
avocado 120 Feb

像上面这样,你可以在 print的参数列表中加入一些字符串或者转义字符之类的东东,让输出的内容格式更漂亮,但一定要记住要使用双引号。

awk 内置 NR 变量表示每一行的行号

$ awk '{print NR "t" $0}' fruit.txt
1 peach  100 Mar 1997 China
2 Lemon  150 Jan 1986 America
3 Pear  240 Mar 1990 Janpan
4 avocado 120 Feb 2008 china

awk 内置 NF 变量表示每一行的列数

$ awk '{print NF "t" $0}' fruit.txt
5 peach  100 Mar 1997 China
5 Lemon  150 Jan 1986 America
5 Pear  240 Mar 1990 Janpan
5 avocado 120 Feb 2008 china

6、awk 中 $NF 变量的使用

$ awk '{print $NF}' fruit.txt
China
America
Janpan
china

上面这个 $NF 就表示每一行的最后一列,因为 NF 表示一行的总列数,在这个文件里表示有 5 列,然后在其前面加上 $ 符号,就变成了 $5 ,表示第 5 列

$ awk '{print $(NF - 1)}' fruit.txt
1997
1986
1990
2008

上面 $(NF-1) 表示倒数第 2 列, $(NF-2) 表示倒数第 3 列,依次类推。

现在除了刚才说的有一个 fruit.txt 文件之外,我们又多了一个新文件叫 company.txt 内容如下

yahoo 100 4500
google 150 7500
apple 180 8000
twitter 120 5000

我们用 fruit.txt 和 company.txt 两个文件来向你演示 awk 同时处理多个文件的时候有什么效果

$ awk '{print FILENAME "t" $0}' fruit.txt company.txt
fruit.txt  peach 100 Mar 1997 China
fruit.txt  Lemon 150 Jan 1986 America
fruit.txt  Pear 240 Mar 1990 Janpan
fruit.txt  avocado 120 Feb 2008 china
company.txt yahoo 100 4500
company.txt google 150 7500
company.txt apple 180 8000
company.txt twitter 120 5000

当你使用 awk 同时处理多个文件的时候,它会将多个文件合并处理,变量 FILENAME 就表示当前文本行所在的文件名称。

看到这里是不是感觉 awk 命令的使用方法真的是简单到爆炸,现在不要太高兴,请举起你的双手跟我一起摇摆。。。哦,不对!请拿起你的双手在电脑上试一试上面这些例子。

7、BEGIN 关键字的使用

在脚本代码段前面使用 BEGIN 关键字时,它会在开始读取一个文件之前,运行一次 BEGIN 关键字后面的脚本代码段, BEGIN 后面的脚本代码段只会执行一次,执行完之后 awk 程序就会退出

$ awk 'BEGIN {print "Start read file"}' /etc/passwd
Start read file

awk 脚本中可以用多个花括号来执行多个脚本代码,就像下面这样

$ awk 'BEGIN {print "Start read file"} {print $0}'
 /etc/passwd
Start read file
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin

8、END 关键字使用方法

awk 的 END 指令和 BEGIN 恰好相反,在 awk 读取并且处理完文件的所有内容行之后,才会执行 END 后面的脚本代码段

$ awk 'END {print "End file"}' /etc/passwd
End file

一定要多动手在电脑上敲一敲这些命令,对身体好。脑子是个好东西,要多用。。。

$ awk 'BEGIN {print "Start read file"} {print $0} END
 {print "End file"}' /etc/passwd
Start read file
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
End file

9、在 awk 中使用变量

可以在 awk 脚本中声明和使用变量

$ awk '{msg="hello world"; print msg}' /etc/passwd
hello world
hello world
hello world
hello world
hello world

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

$ awk 'BEGIN {msg="hello world"} {print msg}' 
/etc/passwd
hello world
hello world
hello world
hello world
hello world

10、在 awk 中使用数学运算

在 awk 中,像其他编程语言一样,它也支持一些基本的数学运算操作

$ awk '{a = 12; b = 24; print a + b}' company.txt
36
36
36
36

上面这段脚本表示,先声明两个变量 a = 12 和 b = 24,然后用 print 打印出 a 加上 b 的结果。

看到上面的输出结果,你很可能又是一脸的懵逼,为什么会重复输出 4 次同样的计算结果。所以说小时不学好,长大做IT。 知识这东西真到了要用的时候,能亮瞎别人的双眼,好了,不废话。请记住 awk 是针对文件的每一行来执行一次单引号 里面的脚本代码,每读取到一行就会执行一次,文件里面有多少行就会执行多少次,但 BEGIN 和 END 关键字后面的 脚本代码除外,如果被处理的文件中什么都没有,那 awk 就一次都不会执行。。。

11、awk 还支持其他的数学运算符

+ 加法运算符
- 减法运算符
* 乘法运算符
/ 除法运算符
% 取余运算符

12、在 awk 中使用条件判断

比如有一个文件 company.txt 内容如下

yahoo 100 4500
google 150 7500
apple 180 8000
twitter 120 5000

我们要判断文件的第 3 列数据,也就是平均工资小于 5500 的公司,然后将其打印输出

$ awk '$3 < 5500 {print $0}' company.txt
yahoo 100 4500
twitter 120 5000

上面的命令结果就是平均工资小于 5500 的公司名单, $3 < 5500 表示当第 3 列字段的内容小于 5500 的时候才会执行后面的 {print $0} 代码块

$ awk '$1 == "yahoo" {print $0}' company.txt
yahoo 100 4500

13、awk 的一些其他的条件操作符

未分类

使用 if 指令判断来实现上面同样的效果

$ awk '{if ($3 < 5500) print $0}' company.txt
yahoo 100 4500
twitter 120 5000

上面表示如果第 3 列字段小于 5500 的时候就会执行后面的 print $0,很像 C 语言和 PHP 的语法对不对。

14、在 awk 中使用正则表达式

在 awk 中支持正则表达式的使用,如果你还对正则表达式不是很了解,请先停下来,上 google 去搜一下。

比如现在我们有这么一个文件 poetry.txt 里面都是我写的诗,不要问我为什么那么的有才华。内容如下:

This above all: to thine self be true
There is nothing either good or bad, but thinking
 makes it so
There’s a special providence in the fall of
 a sparrow
No matter how dark long, may eventually in the
 day arrival

使用正则表达式匹配字符串 “There” ,将包含这个字符串的行打印并输出

$ awk '/There/{print $0}' poetry.txt
There is nothing either good or bad, but
 thinking makes it so
There’s a special providence in the fall
 of a sparrow

使用正则表达式配一个包含字母 t 和字母 e ,并且 t 和 e 中间只能有任意单个字符的行

$ awk '/t.e/{print $0}' poetry.txt
There is nothing either good or bad, but
 thinking makes it so
There’s a special providence in the fall
 of a sparrow
No matter how dark long, may eventually in
 the day arrival

如果只想匹配单纯的字符串 “t.e”, 那正则表达式就是这样的 /t.e/ ,用反斜杠来转义 . 符号 因为 . 在正则表达式里面表示任意单个字符。

使用正则表达式来匹配所有以 “The” 字符串开头的行

$ awk '/^The/{print $0}' poetry.txt
There is nothing either good or bad, but
 thinking makes it so
There’s a special providence in the fall
 of a sparrow

在正则表达式中 ^ 表示以某某字符或者字符串开头。

使用正则表达式来匹配所有以 “true” 字符串结尾的行

$ awk '/true$/{print $0}' poetry.txt
This above all: to thine self be true

在正则表达式中 $ 表示以某某字符或者字符串结尾。

又一个正则表达式例子如下

$ awk '/m[a]t/{print $0}' poetry.txt
No matter how dark long, may eventually in
 the day arrival

上面这个正则表达式 /m[a]t/ 表示匹配包含字符 m ,然后接着后面还要包含中间方括号中表示的单个字符 a ,最后还要包含字符 t 的行,输出结果中只有单词 “matter” 符合这个正则表达式的匹配。因为正则表达式 [a] 方括号中表示匹配里面的任意单个字符。

继续上面的一个新例子如下

$ awk '/^Th[ie]/{print $0}' poetry.txt
This above all: to thine self be true
There is nothing either good or bad,
 but thinking makes it so
There’s a special providence in the fall
 of a sparrow

这个例子中的正则表达式 /^Th[ie]/表示匹配以字符串 “Thi” 或者 “The” 开头的行,正则表达式方括号中表示匹配其中的任意单个字符。

再继续上面的新的用法

$ awk '/s[a-z]/{print $0}' poetry.txt
This above all: to thine self be true
There is nothing either good or bad,
 but thinking makes it so
There’s a special providence in the
 fall of a sparrow

正则表达式 /s[a-z]/ 表示匹配包含字符 s 然后后面跟着任意 a 到 z 之间的单个字符的字符串,比如 "se", "so", "sp" 等等。

正则表达式 [] 方括号中还有一些其他用法比如下面这些

  • [a-zA-Z] 表示匹配小写的 a 到 z 之间的单个字符,
    或者大写的 A 到 Z 之间的单个字符

  • [^a-z] 符号 ^ 在方括号里面表示取反,
    也就是非的意思,
    表示匹配任何非 a 到 z 之间的单个字符

正则表达式中的星号 * 和加号 + 的使用方法

$ awk '/go*d/{print $0}' poetry.txt
There is nothing either good or bad,
 but thinking makes it so

上面这个表示匹配包含字符串 "god",并且中间的字母 "o" 可以出现 0 次或者多次,比如单词 "good" 就符合这个要求。 正则表达式中的 + 和星号原理差不多,只是加号表示任意 1 个或者 1 个以上,也就是必须至少要出现一次。

正则表达式问号 ? 的使用方法

$ awk '/ba?d/{print $0}' poetry.txt
There is nothing either good or bad,
 but thinking makes it so

正则表达式中的问号 ? 表示它前面的字符只能出现 0 次 或者 1 次,也就是可以不出现,也可以出现,但如果有出现也只能出现 1 次。

正则表达式中的 {} 花括号用法

$ awk '/go{2}d/{print $0}' poetry.txt
There is nothing either good or bad,
but thinking makes it so

花括号 {} 表示规定它前面的字符必须出现的次数,像上面这个 /go{2}d/ 就表示只匹配字符串 "good",也就是中间的字母 "o" 必须要出现 2 次。

正则表达式中的花括号还有一些其他的用法如下

  • /go{2,3}d/ 表示字母 "o" 只能可以出现 2 次或者 3 次
  • /go{2,10}d/ 表示字母 "o" 只能可以出现 2次,
    3次,4次,5次,6次 … 一直到 10 次
  • /go{2,}d/ 表示字母 "o" 必须至少出现 2 次
    或着 2 次以上

正则表达式中的圆括号的用法

$ awk '/th(in){1}king/{print $0}' poetry.txt
There is nothing either good or bad,
 but thinking makes it so

正则表达式中的圆括号表示将多个字符当成一个完整的对象来看待。比如 /th(in){1}king/ 就表示其中字符串 "in" 必须出现 1 次。而如果不加圆括号就变成了 /thin{1}king/ 这个就表示其中字符 "n" 必须出现 1 次。

看到这里,如果你对 poetry.txt 件中写的诗比较熟悉,你就会发现。。。我去!这诗根本就不是我写的。所以论多读书是多么的重要。我有幸借用莎士比亚的诗来向你讲解如何在 awk 中使用正则表达式。

15、使用awk的一些总结

因为 awk 算起来也是一种编程语言,它的功能远远不止我们上面讲的这些,awk 还有一些其他比较复杂的功能。但一般我们不建议将 awk 用的太过于复杂。通常面对一些比较复杂的场景我们还是要使用其他的一些工具,比如 shell 脚本,Lua 等等

Awk获取shell外部变量值

这里提到awk,相信写shell的朋友都会接触到。AWK 是一种用于处理文本的编程语言工具。AWK 提供了极其强大的功能:

  • 可以进行正则表达式的匹配
  • 样式装入
  • 流控制
  • 数学运算符
  • 进程控制语句
  • 内置的变量和函数

可以把awk看作一门完全的程序设计语言,它处理文本的速度是快得惊人的。现在很多基于shell 日志分析工具都可以用它完成。设计简单,速度表现很好。 涉及到以上六个方面内容,我会在以后文章中加以介绍。 这次主要说下,怎么样把外部变量传入到awk执行语句中。

一、基础:

awk [ -F re] [parameter...] ['pattern {action}' ] [-f progfile][in_file...]

awk一般语法如上面所说。

如:

[chengmo@ localhost ~]$ echo 'awk code' | awk 'BEGIN{print "startn============="}{print $0}END{print "=========nend"}'
start
=============
awk code
=========
end

在 awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。

二、获得外部变量方法

1、获得普通外部变量

[chengmo@ localhost ~]$ test='awk code'
[chengmo@ localhost ~]$ echo | awk '{print test}' test="$test"
awk code
[chengmo@ localhost ~]$ echo | awk test="$test" '{print test}'
awk: cmd. line:1: fatal: cannot open file `{print test}' for reading (No such file or directory)

格式如:awk ‘{action}’ 变量名=变量值 ,这样传入变量,可以在action中获得值。 注意:变量名与值放到’{action}’后面。

[chengmo@ localhost ~]$ echo | awk ‘BEGIN{print test}’ test=”$test”

这种变量在:BEGIN的action不能获得。

2、BEGIN程序块中变量

[chengmo@ localhost ~]$ test='awk code'
[chengmo@ localhost ~]$ echo | awk -v test="$test" 'BEGIN{print test}'
awk code
[chengmo@ localhost ~]$ echo | awk -v test="$test" '{print test}'
awk code

格式如:awk –v 变量名=变量值 [–v 变量2=值2 …] ‘BEGIN{action}’ 注意:用-v 传入变量可以在3中类型的action 中都可以获得到,但顺序在 action前面。

3、获得环境变量

[chengmo@ localhost ~]$ awk 'BEGIN{for (i in ENVIRON) {print i"="ENVIRON[i];}}'
AWKPATH=.:/usr/share/awk
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
LANG=en_US.UTF-8
.......

只需要调用:awk内置变量 ENVIRON,就可以直接获得环境变量。它是一个字典数组。环境变量名 就是它的键值。

使用awk获取每行的最大值

需求

  • 有一个数字文本,每行都是数字,以空格分开;现在需要将每行中最大值取出来

文本如下:

[root@localhost ~]#cat urfile
1   1     2
1   2     1
1   3     1
  • 使用awk解决
[root@localhost ~]#awk 'BEGIN{n=1;max=0;nu=0}{for(n=1;n=max)max=a[$n]}{print max}{max=0}}' urfile
2
2
3

解释说明

使用数组将每个数字记录,然后将每个值与max变量比较,若比max大,则将内容赋予max;使用nu记录行号,每行执行最后将max置0

awk用法与示例介绍

awk:模式扫描和数据处理语言

描述: awk是一种编程语言,用于Linux/unix下对文本和数据进行扫描与处理,数据可以来自标准输入、文件、管道。工作流程是:逐行扫描文件,寻找特定匹配模式的行,并进行相应的处理动作。awk读取文件文件内容每一行时,将对比该行是否与给定的模式相匹配,如果匹配,则执行相应处理动作,否则不对该行进行处理。如果没有指定的处理脚本,则把匹配的行显示到标准输出(默认print动作),如果没有指定模式匹配,则默认匹配所有数据

语法:

awk  [ POSIX or GNU style options ] -f program-file [ --  ] file ...
awk [ POSIX or GNU style options ] [ --  ]  program-text file ...

选项:

  • -F fs 使用fs作为输入行的分隔符(默认是空格或者制表符)

  • -v var=val 在处理过程之前,给var设置一个变量val

  • -f program-file 从文件中读取awk的处理内容

内置变量:

  • ARGC 命令行参数个数

  • ARGV 命令行参数的一个排列,索引从0到ARGC-1

  • ARGIND ARGV最近处理文件的索引

  • FILENAME 当前输入文档的名称

  • FNR 当前输入文档的记录编号

  • NR 输入流的当前记录编号(行号)

  • FS 字段分隔符

  • NF 当前记录的字段个数

  • OFS 输出字段分隔符,默认为空格

  • RS 输出记录分隔符默认是换行符n

  • ORS 输出记录分隔符,默认是换行符n

AWK patterns may be one of the following:

BEGIN
END
/regular expression/
relational expression
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
(pattern)
! pattern
pattern1, pattern2

例子:

1、-F 指定分隔符

[root@python ~]# cat test.txt
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol  
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/tcp               # iqobject
[root@python ~]# awk '{print $2}' test.txt
48049/tcp
48128/udp
48129/tcp
48129/udp
48556/udp
48619/tcp
[root@python ~]# awk -F'/' '{print $2}'             test.txt
tcp               # 3GPP Cell Broadcast         Service Protocol
udp               # Image Systems Network       Services
tcp               # Bloomberg locator
udp               # Bloomberg locator
udp               # com-bardac-dw
tcp               # iqobject

#指定空格或者/作为分分隔符。+代表重复前面的字符一次或者多次
[root@python ~]# awk -F'[ /]+' '{print $2}'         test.txt
48049
48128
48129
48129
48556
48619

2、-v 变量赋值

[root@python ~]# awk -v a=2 '{print $a}' test.txt
48049/tcp
48128/udp
48129/tcp
48129/udp
48556/udp
48619/tcp
[root@python ~]# awk -v a=342 'BEGIN{print a}'
342

3、-f 从文件中读取awk的内容

#编辑awk脚本文件
[root@python ~]# cat a.txt 
/^$/ {print "BLANK LINE"}
#有几个空行就打印多少行的BLANK LINE
[root@python ~]# awk -f a.txt /etc/ssh/ssh_config
BLANK LINE
BLANK LINE
BLANK LINE
BLANK LINE

4、记录和字段

#$0表示将匹配的内容完全输出
[root@python ~]# echo "I am a bird"|awk '{print $0}'
I am a bird
[root@python ~]# echo "I am a bird"|awk '{print $1,$2}'
I am

#NF表达总的字段的个数(可以理解为列数)
[root@python ~]# echo "I am a bird"|awk '{print NF}'
4

#$NF表示最后一个字段
[root@python ~]# echo "I am a bird"|awk '{print $NF}'
bird

#NR表示输入流的当前记录编号,可以理解为(匹配的行编号)
[root@python ~]# echo "I am a bird"|awk '{print NR}'
1
[root@python ~]# echo -e "I am a birdnhello"|awk '{print NR}'
1
2

5、OFS指定输出的分隔符

echo "I am a bird"|awk 'BEGIN{OFS="#"}{print $1,$2,$3,$4}'
I#am#a#bird

6、正则匹配

#匹配含有tcp的行
[root@python ~]# awk '/tcp/{print $0}' test.txt
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
blp5            48129/tcp               # Bloomberg locator
iqobject        48619/tcp               # iqobject

#匹配以blp5开头的行
[root@python ~]# awk '/^blp5/{print $0}' test.txt
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator

#匹配以tor结束的行
[root@python ~]# awk '/tor$/{print $0}' test.txt
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator

#逻辑或||
[root@python ~]# awk '/blp5/||/3gpp/{print $0}' test.txt
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator

#逻辑与&&
[root@python ~]# awk '/blp5/&&/tcp/{print $0}' test.txt
blp5            48129/tcp               # Bloomberg locator

#逻辑非
[root@python ~]# awk '!/blp5/&& !/3gpp/{print $0}' test.txt
isnetserv       48128/udp               # Image Systems Network Services
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/tcp               # iqobject

7、匹配范围

[root@python ~]# awk '/3gpp/,/blp5/{print $0}' test.txt
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/tcp               #       Bloomberg locator

8、BEGIN和END格式(打印标签)

#打印行首
[root@python ~]# awk 'BEGIN{print "SERVICEttPORTtttDESCRIPION"}{print $0}' test.txt
SERVICE         PORT                    DESCRIPION
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/tcp               # iqobject

#打印行尾
[root@python ~]# awk '{print $0}END{print "The ending..."}' test.txt
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/tcp               # iqobject
The ending...

#行首行尾都打印
[root@python ~]# awk 'BEGIN{print "SERVICEttPORTtttDESCRIPION"}{print $0}END{print "The ending..."}' test.txt
SERVICE         PORT                    DESCRIPION
3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/tcp               # Bloomberg locator
blp5            48129/udp               # Bloomberg locator
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/tcp               # iqobject
The ending...

9、表达式与操作符:如果在awk定义的变量中没有初始化,则初始值为空字符串或者0,字符操作一定要加引号(a=”How are you”)。

#统计所有的空白行
[root@python ~]# awk '/^$/{print x+=1}' /etc/ssh/ssh_config
1
2
3
4

#打印出空白行的总个数
[root@python ~]# awk '/^$/{x+=1}END{print x}' /etc/ssh/ssh_config
4

#~(匹配) 、!~(不匹配).打印出root的ID号。匹配第一个字段为root的行,打印出其UID
[root@python ~]# awk -F':' '$1~/root/{print $3}' /etc/passwd
0

#打印出UID大于400的用户
[root@python ~]# awk -F':' '$3>400{print $1}' /etc/passwd
saslauth
mysql
dianel
[root@python ~]# awk -F':' '$3>400{x+=1}END{print x}' /etc/passwd
3

10、awk的高级应用

if条件判断

#判断boot分区可用容量小于20M时报警,否则就显示OK
[root@python ~]# df|grep 'boot'|awk '{if($4<20000)print"alart";else print "ok"}'
ok

[root@python ~]# seq 5|awk '{if($0==3)print $0}'
3
[root@python ~]# seq 5|awk '{if($0==3)print $0;else print "no"}'
no
no
3
no
no

while循环:语法格式

while (condition) statement
do statement while (condition)

两种格式:

#因为i和total都初始化,默认为0
[root@python ~]# awk 'BEGIN{do {i++;total+=i}while(i<100)print total}' 
5050

[root@python ~]# awk 'BEGIN{while(i<100){i++;total+=i}print total}' 
5050

for循环:语法格式

1.for (expr1; expr2; expr3) statement
2.for (var in array) statement

[root@python ~]# awk 'BEGIN{for(i=0;i<101;i++){total+=i} print total}'
5050

break和continue

  • break:跳出循环

  • continue:终止当前循环

打印IP:

[root@python ~]# ifconfig eth0|awk '/Bcast/'|awk -F'[ :]+' '{print $4}'
192.168.1.13