命令格式
awk '{pattern + action}' {filenames}
awk '条件1{动作1}条件2{动作2}...' 文件名
eg
awk '{print $0}' /etc/passwd
调用 awk时,我们指定/etc/passwd 作为输入文件。执行 awk时,它依次对/etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout,所得到的结果与执行 cat /etc/passwd 完全相同。
awk会根据空格和制表符,将每一行分成若干字段,依次用$1、$2、$3代表第一个字段、第二个字段、第三个字段等等。
#! /bin/bash
echo "hello world" | awk '{print $2}'
输出结果
world
内置参数/变量
内置参数 | 说明 |
---|---|
$0 | 表示整个当前行 |
$1 | 每行第一个字段 |
$2 | 每行第二个字段 |
NR | number of Row 行号,当前处理的文本行的行号。 |
NF | number of Field,当前行的字段的个数(即当前行被分割成了几列),字段数量 |
FILENAME | 正在处理的文件名 |
FS | 输入字段分隔符, 默认为空白字符 |
OFS | 输出字段分隔符, 默认为空白字符 |
ARGC | 命令行参数的个数 |
ARGV | 数组,保存的是命令行所给定的各参数 |
NF
变量NF表示当前行有多少个字段,因此$NF就代表最后一个字段。$(NF-1)代表倒数第二个字段。
#! /bin/bash
echo 'hello world' | awk '{print $NF}'
echo 'hello world' | awk '{print $(NF-1)}'
输出结果
world
hello
NR
测试文件demo.txt
123 abc
456 def
789 ghi
bash内容
#! /bin/bash
awk '{print "["NR"]",$0}' demo.txt
输出结果
[1] 123 abc
[2] 456 def
[3] 789 ghi
FNR
各文件分别计数的行号
准备两个测试文件
a.txt
a1 b1
c2 d2
b.txt
good study
day up
执行
#! /bin/bash
awk '{print "["NR"]",$0}' a.txt b.txt
输出结果
[1] a1 b1
[2] c2 d2
[3] good study
[4] day up
执行FNR
#! /bin/bash
awk '{print "["FNR"]",$0}' a.txt b.txt
输出结果如下,当awk处理多个文件时,FNR分别对每个文件的行数进行计数。
[1] a1 b1
[2] c2 d2
[1] good study
[2] day up
RS
RS是输入行分隔符,如果不指定,默认的”行分隔符”就是我们所理解的”回车换行”。
,我们不想以默认的”回车换行”作为”行分隔符”,而是想使用空格作为所谓的行分隔符,也就是说,我们想让awk认为,每遇到一个空格,就换行,换句话说,我们想让awk以为每次遇到一个空格就是新的一行。
a1 b1
c2 d2
执行
#! /bin/bash
awk -v RS=' ' '{print "["NR"]",$0}' a.txt
输出结果如下,指定使用空格作为”行分隔符”时,在awk解析文本时,每当遇到空格,awk就认为遇到的空格是换行符,于是awk就将文本换行了,而文本本身的”回车换行”,对于awk来说并不是所谓的换行符,所以才会出现上图中第3行的现象,
[1] a1
[2] b1
c2
[3] d2
ARGV
ARGV内置变量表示的是一个数组,这个数组中保存的是命令行所给定的参数,其中ARGV[0]表示awk本身
#! /bin/bash
awk 'BEGIN{print ARGV[1],ARGV[2]}' a b
输出结果
a b
ARGC
则表示参数的数量
awk 'BEGIN{print ARGV[1],ARGV[2],ARGC}' a b
输出结果
3
自定义环境变量
方法1 -v varname=value 变量名区分字符大小写。
方法2 在program中直接定义。
#! /bin/bash
v='abc'
awk -v myvar=$v 'BEGIN{print myvar}'
或者变量定义与动作之间需要用分号”;”隔开
awk 'BEGIN{myvar="abc"; print myvar}'
分隔符
分隔符 | 说明 |
---|---|
输入分隔符field separator(FS) | 默认以空白字符为分隔符对每一行进行分割。 |
输出分割符output field separator(0FS) | 默认的输出分割符也是空格。 |
输入分隔符
默认分隔符是空格 -F 指定分隔符
awk -F ':' '{print $1}' /etc/passwd
awk -F ':' '{print "Line: " NR, "Col: " NF,"User: " $1}' /etc/passwd
awk -F ':' '{printf("Line:%s Col:%s User:%s\n",NR,NF,$1)}' /etc/passwd
awk -F ':' '{if ($3>100) print "User:" $1}' /etc/passwd
准备测试文件test.txt
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
shell 文件
#! /bin/bash
awk -F ':' '{print $1}' test.txt
输出结果
root
daemon
bin
sys
sync
awk内置变量FS可以用于指定输入分隔符,但是在使用变量时,需要使用-v选项,-v表示设置变量值
测试文件demo.txt
123#abc
456#def
789#ghi
shell 测试文件
#! /bin/bash
awk -v FS='#' '{print $1,$2}' demo.txt
输出结果
123 abc
456 def
789 ghi
输出分隔符
内置变量OFS来设定awk的输出分隔符,使用内置变量的需要配合使用-v选项
#! /bin/bash
awk -v FS='#' -v OFS='*' '{print $1,$2}' demo.txt
输出结果
123*abc
456*def
789*ghi
取消分隔符
awk ‘{print $1 $2}’ 表示每行分割后,将第一列(第一个字段)和第二列(第二个字段)连接在一起输出。
awk ‘{print $1,$2}’ 表示每行分割后,将第一列(第一个字段)和第二列(第二个字段)以输出分隔符隔开后显示。
#! /bin/bash
awk -v FS='#' '{print $1$2}' demo.txt
输出结果
123abc
456def
789ghi
逻辑判断
语法
awk '条件 动作' 文件名
==,!=,<,>判断逻辑表达式
awk -F ':' '$3>100{print $1,$3}' /etc/passwd
函数
- tolower():字符转为小写。
- length():返回字符串长度。
- substr():返回子字符串。
- sin():正弦。
- cos():余弦。
- sqrt():平方根。
- rand():随机数