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

results matching ""

    No results matching ""