awk基础
简介
awk程序的报告生成能力通常用来从大文件文本文件中提取数据元素并将它们格式化成可读的报告。awk程序允许从日志文件中只过滤出你要看的数据元素,并以某种更容易读取重要数据的方式将他们格式化。awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk命令格式
awk options program file
从命令行中读取程序脚本
awk '{print "Hello john!"}'
如果输入一行文本并按下回车键,awk会对这行文本运行一遍所有的程序脚本
使用数据字段变量
cat data3
awk '{print $1}' data3
在程序脚本中使用多个命令
#用分号分隔命令
echo "My name is Rich" | awk '{$4="Christine";print $0}'
从文件中读取程序
cat script2
awk -F: -f script2 /etc/passwd #-f后接脚本文件
'{print $1 "'\''" "s home directory is" $6}' /etc/passwd
在处理数据前运行脚本
BIGIN:强制awk在读取数据前执行BEGIN关键字后指定的程序脚本
END:强制awk在读完数据后执行BEGIN关键字后指定的程序脚本
'BEGIN {print "The data4 File Contents:"} {print $0}' data4
awk 'BEGIN {print "The data4 File Begins:"}{print $0} END {print "The data4 File Ends"}' data4
cat script4
awk -f script4 /etc/passwd
awk进阶
使用变量
cat data1
awk 'BEGIN{FS=",";OFS="---"}{print $1,$2,$3}' data1
FIILEDWIDTHS变量允许你读取数据行,而不用字段分隔符来划分字段。一旦设置了FIEILDWIDTH变量,awk就会忽略FS变量,而根据提供的字段宽度大小来计算字段
cat data1b
awk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1b
cat data2
awk 'BEGIN{FS="\n";RS=""} {print $1,$4}' data2 #将\n作为字段分隔符,则每行为一个字段,将""作为行分隔符,则空白行为行分隔符
数据变量
NR,表示awk开始执行程序后所读取的数据行数.
FNR,与NR功用类似,不同的是awk每打开一个新文件,FNR便从0重新累计.
awk '{print NR, $0}' file1
awk '{print NR, $0}' file1 file2
awk '{print FNR, $0}' file1 file2
#打印第2行
awk 'NR==2 {print NR, $0}' file1 file2
另一种做法
sed -n 2p file1 file2
自定义变量
在脚本中给变量赋值
awk 'BEGIN{testing="This is a test";print testing;testing=45;print testing}'
在命令行上给变量赋值
cat script1
awk -f script1 n=2 data1
-v 允许指定在BEGIN代码之前设定的变量
#script1
BEGIN {print "The starting value is ",n; FS=","}
{print $n}
awk -v n=4 -f script1 data1
处理数组
定义数组
awk 'BEGIN{
var[1] = 34
var[2] = 3
total = var[1] + var[2]
print total
}'
遍历数组变量
awk 'BEGIN{
var["a"] = 1
var["g"] = 2
var["m"] = 3
var["u"] = 4
delete var["g"]
for(test in var)
{
print "Index:",test,",value:",var[test]
}
}'
索引值不会按特定顺序返回
awk 'BEGIN{
var["a"] = 1
var["g"] = 2
var["m"] = 3
var["u"] = 4
delete var["g"]
for(test in var)
{
print "Index:",test,",value:",var[test]
}
}'
使用模式
正则表达式
awk 'BEGIN{FS=","} /11/{print $1}' data1 #匹配含有11的行
匹配操作符~
$1 ~ /^data/
#$1代表数据行中的第一个数据字段,这个表达式会过滤出第一个字段以文本data开头的所有数据行
awk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1 #用/^data2/来匹配第2个数据字段,该正则表达式指明字符串要以data2开头
awk -F: '$1 ~ /root/{print $1,$NF}' /etc/passwd
#排除匹配的行
$1 !~ /expression
数字表达式
awk -F: '$4 == 0{print $1}' /etc/passwd #显示所有属于root用户组(组ID为0)的系统用户
awk -F, '$1=="data11"{print $1}' data1
结构化命令
if语句
awk '{if($1 > 20) print $1}' data4
awk '{
if($1 > 20)
{
x = $2 * 2
print x
}
}' data4
cat data4
awk '{
if($1 > 20)
{
x = $2 * 2
print x
}else
{
x = $1 / 2
print x
}
}' data4
cat data5
awk '{
total = 0
i = 1
while(i < 4){
total += $i
i++
}
avg = total /3
print "Average:",avg
}' data5
格式化打印
cat data2
awk 'BEGIN{FS="\n";RS=""} {printf "%s %s\n",$1, $4}' data2
awk 'BEGIN{FS="\n";RS=""} {printf "%-16s %s\n",$1, $4}' data2 #第一个字段占16个字节,左对齐
函数
字符串函数
awk 'BEGIN{x = "testing"; print toupper(x);print length(x)}'
split函数:将s用FS字符或正则表达式r(如果指定了的话)分开当道数组a中。返回字段总数
cat data1
awk 'BEGIN{FS=","}{split($0, var);print var[1], var[5]}' data1
自定义函数
awk '
function myprint()
{
printf "%-16s %s\n", $1, $4
}
BEGIN{FS="\n";RS=""}
{
myprint()
}' data2