awk 认为文件中的每一行是一条记录 记录与记录的分隔符为换行符
每一列是一个字段 字段与字段的分隔符默认为空格
awk
awk options program file
获取指定时间端的日志 awk '$4>="[31/Jan/2018:16:00:00" && $4<="[31/Jan/2018:16:30:00"' log
或 awk '{split($4,array,"[");if(array[2]>="31/Jan/2018:17:00:00" && array[2]<="31/Jan/2018:17:30:00"){print $0}}' log
统计日志uv awk '{a[$1]++} END{for(i in a)print i,a[i]}' localhost_access_log.2016-10-12.txt | wc -l
pv wc -l localhost_access_log.2016-10-12.txt
列转行
awk '{for(i=0;++i<=NF;)a[i]=a[i]?a[i] FS $i:$i}END{for(i=0;i++<NF;)print a[i]}' 1.txt
name age alice 21 ====> ryan 30
行加求和 awk '{
sum=0
for(n=1;n<5;n++)
(sum+=$n)
print sum}' t2
列加求和 awk '{sum +=$1}END{print sum}' t2
-F fs 指定描绘一行中数据字段的文件分隔符 默认为空格
-f file 指定读取程序的文件名
-v var=value 定义awk程序中使用的变量和默认值
-mf N 指定数据文件中要处理的字段的最大数目
-mr N 指定数据文件中的最大记录大小
-w keyword 指定awk的兼容模式或警告级别
awk 程序脚本由左大括号和右大括号定义。脚本命令必须放置在两个大括号之间。由于awk命令行假定脚本是单文本字符串,
所以必须将脚本包括在单引号内。
$0 表示整行文本
$1 表示文本行中的第一个数据字段
$2 表示文本行中的第二个数据字段
$N N
$NF
通过awk进行输出排列
将/etc/passwd文件中的 描述:UID:GID:shell按顺序输出【$5 $3 $4 $7】
输出格式如:
username: root UID: 0 GID: 0 SHELL: /bin/bash
echo "my name is rich" | awk '{$4="dave";print $0}'
从文件中读取程序
[root@VFAST ~]# vim script2
{
print $5 "'s userid is " $1
}
[root@VFAST ~]# awk -F: -f script2 /etc/passwd
在处理数据之前运行脚本 【插入文件头】
[root@VFAST ~]# awk 'BEGIN {print "hello world!"}'
hello world!
高级awk command
awk 支持两种不同类型的变量
内置变量
用户自定义变量
内置变量
1.字段和记录分隔符变量
数据字段变量
允许使用美元符和数据字段在记录中的数字位置引用数据记录中的单个数据字段 $1 $2 $n
数据字段由字段分隔符号描述 默认为空格
FS内置变量属于一组内置变量,他们用于控制awk在输入数据和输出数据中处理字段和记录的方式
awk数据字段和记录变量
变量 描述
FIELDWIDTHS 以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
FS 输入字段分隔符号
RS 输入记录分隔符
OFS 输出字段分隔符号
ORS 输出记录分隔符号
cat /etc/passwd
[root@VFAST ~]# awk -F: '{print $1,$2,$3}' /etc/passwd
等价
[root@VFAST ~]# awk 'BEGIN {FS=":"} {print $1,$2,$3} ' /etc/passwd
[root@VFAST ~]# awk 'BEGIN {FS=":";OFS="-"} {print $1,$2,$3} ' /etc/passwd
FIELDWIDTHS 变量允许不使用字段分隔符读取记录,在某些应用程序中,数据不使用字段分隔符号,而是被放置的特定列中,
在这种情况下必须使用FIELDWIDTHS变量以匹配记录中的数据布局
vim data3
1005.324759.37
115-2.349194.00
05b10.1298100.1
[root@VFAST ~]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"}''{print $1,$2,$3,$4}' data3
100 5.324 75 9.37
115 -2.34 91 94.00
05b 10.12 98 100.1
RS ORS变量定义awk程序处理数据流中记录的方式,默认情况是换行符
RS默认变量值表示输入数据流中文本的每个新行为一条新纪录
有时数据字段分布在数据流的多行上,典型的例子是包含地址和电话号码的数据,他们分别在单独的行上
[root@VFAST ~]# cat data7
Riley Mullen
123 Main Street
Chicago,IL 60602
(312)555-1234
[root@VFAST ~]# awk 'BEGIN{FS="\n";RS=""} {print $1,$4}' data7
Riley Mullen (312)555-1234
将RS变量设置问空字符串,然后再数据流中的数据记录之间保留一个空行,awk会将每个空行解析为记录的分隔符
[root@VFAST ~]# cat data7 |awk 'BEGIN{FS="\n";RS=""}{print $1,$2,$3,$4}'
Riley Mullen 123 Main Street Chicago,IL 60602 (312)555-1234
[root@VFAST ~]# awk 'BEGIN{FS="\n";OFS="-"} {print $1,$2,$3,$4}' data7
Riley Mullen---
123 Main Street---
Chicago,IL 60602---
(312)555-1234---
vim vfast
123
456 789
123456
789
awk 'BEGIN{RS="\n";ORS="***"}{print $0}' vfast
用户自定义的变量
在脚本中附值变量
[root@VFAST ~]# awk 'BEGIN{
> testing="this is a test"
> print testing
> testing=45
> print testing
> }'
this is a test
45
数学计算
[root@VFAST ~]# awk 'BEGIN{x=4;x=x*2+3;print x}'
11
在命令行中附值变量
vim script0
BEGIN{FS=":"}
{print $n}
[root@VFAST ~]# awk -f script0 n=1 /etc/passwd
将$n变量附值为1
使用数组
awk 使用关联数组,其不同于数字数组,他的索引值可以是任何文本字符串,不需要使用使用一系列的数字来标识数组中包含的数组元素。
关联数组由引用各个值的混杂的字符串构成。每个索引必须唯一。且唯一标识分配给它的数据元素
定义数组变量
var[index]=element
var是变量名称,index是关联数组的索引值,而element是数据元素值
EXAMPLES:
var[1]=1
var[2]=2
[root@VFAST ~]# awk 'BEGIN{
> var[1]=1
> var[2]=2
> total=var[1]+var[2]
> print total
> }'
通过计算结果为3
3
awk 'NR==1{print $2}' /proc/meminfo 取/proc/memeinfo文件的第一列的第一行
NR 指定行号
打印第一行 第二行数值
awk 'NR==1{t=$2}NR==2{f=$2;print f/t*100}' /proc/meminfo
vim aa
1
2
3
4
awk '{ sum += $1 } END { print sum}' aa
awk 'END{print NR}' test 统计test有多少行
awk 'END{print $0}' test 打印最后一行
awk 'END{print NF}' test 统计列数
2.3. 条件操作符:
<、<=、==、!=、>=、~ 匹配正则表达式、!~不匹配正则表达式
匹配字符串
== 精确匹配
!=取反
awk -F: '$1=="root"{print $0}' /etc/passwd
awk -F: '$1!="root"{print $0}' /etc/passwd
~
!~ 模糊匹配
awk -F: '$1 ~ "ro"{print $0}' /etc/passwd
awk -F: '$1 !~ "ro"{print $0}' /etc/passwd
数字匹配
> < >= <= ==
vim file
1
2
3
4
awk '$1>2{print $0}' file
awk '$1>=2{print $0}' file
awk '$1<2{print $0}' file
awk '$1<=2{print $0}' file
awk '$1==2{print $0}' file
匹配:awk '{if ($4~/ASIMA/) print $0}' temp 表示如果第四个域包含ASIMA,就打印整条
精确匹配:awk '$3=="48" {print $0}' temp 只打印第3域等于"48"的记录
不匹配: awk '$0 !~ /ASIMA/' temp 打印整条不包含ASIMA的记录
不等于: awk '$1 != "asima"' temp
小于: awk '{if ($1<$2) print $1 "is smaller"}' temp
设置大小写: awk '/[Gg]reen/' temp 打印整条包含Green,或者green的记录
任意字符: awk '$1 ~/^...a/' temp 打印第1域中第四个字符是a的记录,符号’^’代表行首,符合’.’代表任意字符
或关系匹配: awk '$0~/(abc)|(efg)/' temp 使用|时,语句需要括起来
AND与关系: awk '{if ( $1=="a" && $2=="b" ) print $0}' temp
OR或关系: awk '{if ($1=="a" || $1=="b") print $0}' temp
awk 函数
awk '{ if ( $1 > 9) print $1}'
10
awk `{if ($1 > 9) print $1 * 2} data`
20
or
awk '{
if ($1 > 9)
{
x=$1 * 2
print x
}}' data
else
awk '{ if ( $1 > 9 ) print $1 * 2;else print $1/2 }' data
or
awk '{if ($1>9)
{
x=$1 * 2
print x
}
else
{
y=$1 / 2
}}' data
while语句
while (condition)
{
satements
}
cat data1
1 2 3
4 5 6
7 8 9
awk '{
total = 0
i = 1
while ( i < 4 )
{
total += $i
i++
}
print total
}' data1
total +=$i
i++
的意思是将data1中的1 到3 个字段累加
break continue
awk '{
total = 0
i = 1
while ( i < 4 )
{
total += $i
if (i == 2)
break
i++
}
print total
}' data1
输出结果$1 + $2
awk '{
total = 0
for (i=1;i<4;i++)
{
total += $i
}
print total
}' data1
输出结果
$1+$2+$3的和
do-while
在检查之前执行语句
do
{
statements
}while (condition)
awk '{
total = 0
i = 1
do
{
total += $i
i++
}while (total < 150)
print total}' data1
判断total的值是否大于150 如果不大于150和后一个字段累加 如果大于150则输出该字段 如果累加大于150则不在往后累加
关于while例子
awk '{
a=0
i=1
do
{
a+=$i
i++
}
while (a>150)
print a
}' data
10
7
3
[root@instructor tmp]# awk '{
a=0
i=1
do
{
a+=$i
i++
}
while (a<150)
print a
}' data
263
187
287
错误死循环
[root@instructor tmp]# awk '{
a=0
i=1
do
{
a+=$i
i++
}
while (a>150)
print a
}' data
[root@instructor tmp]# cat data1
100 110 20
160 150 140
130 10 20
当第二行$1是160 符合while条件为真,则继续累加$2 依然大于150 继续累加$3依然大于150 条件永远为真 自然不会跳出循环
system函数
在awk中调用系统shell命令
awk 'BEGIN{system("echo hello")}'
hello
or
[root@baism 桌面]# awk 'BEGIN{system("date")}'
2014年 04月 30日 星期三 11:06:23 CST
注意 一定要把system("") 中的命令用双引号引起来
cat a.txt
192.168.1
192.168.2
192.168.3
172.16.3
192.16.1
192.16.2
192.16.3
10.0.4
期望输出
192.168.1-192.168.3
172.16.3
192.16.3-192.16.1
10.0.4
[root@instructor ~]# awk 'BEGIN{RS="";FS="\n";OFS="\n"}{print $1 "-" $3,$4,$7 "-" $4,$8}' aa.txt
192.168.1-192.168.3
172.16.3
192.16.3-172.16.3
10.0.4
zhangsan
Beijing.China
[email protected]
010-12345678
wangwu
Tianjin.China
[email protected]
010-23456789
awk 'BEGIN{RS="";FS="\n"}{print "~~~~~~~~~~~~~~~~~~~~~~~~"}{print $1,$2 "\n" $3,$4}' data