第一种形式
awk 'BEGIN{}pattern{commands}END{}' file_name
cat file_name | awk 'BEGIN{}pattern{commands}END{}'
n内置变量 | 含义 |
---|---|
$0 | 整行内容 |
1 − 1- 1−n | 当前行的第1-n个字段 |
NF | 当前行的字段个数,即多少列 |
NR | 当前行的行号,从1开始计数 |
FNR | 多个文件处理时,每个文件行号单独计数,都是从0开始 |
FS | 输入字段分隔符。不指定默认以空格或tab分割 |
RS | 输入行分割符,默认回车换行 |
OFS | 输出字段分隔符,默认空格 |
ORS | 输出行分隔符。默认回车 |
FILENAME | 当前输入的文件名 |
ARGC | 命令行参数个数 |
ARGV | 命令行参数数组 |
java:python:scala
hadoop:spark:flume
jake:mike:coco
awk 'BEGIN{FS=":"}{print $1}' list # BEGIN中指定分隔符为:
awk 'BEGIN{FS=":"}{print NR}' list # 显示行号
awk 'BEGIN{FS=":"}{print NF}' list # 显示每行的列数
awk 'BEGIN{FS=":"}{print NF}' list list #行号为连续显示
awk 'BEGIN{FS=":"}{print FNR}' list list1 # 每个文件是单独计算行号
awk 'BEGIN{FS=":"}{print $NF}' list # 输出最后一列
格式符 | 含义 |
---|---|
%s | 打印字符串 |
%d | 打印十进制数 |
修饰符 | 含义 |
---|---|
- | 左对齐 |
+ | 右对齐 |
+ | 显示8进制在前面加0,显示16进制在前面加0x |
以字符串格式化打印 /etc/passwd中的第七个字段,并且以":" 作为分隔符
awk 'BEGIN{FS=":"} {printf "%s:",$7}' /etc/passwd
以10进制打印/etc/passwd中第三个字段,以":"作为分隔
awk 'BEGIN{FS=":"} {printf "%10d\n",$3}' /etc/passwd # 右对齐10个字符
浮点数打印
awk 'BEGIN{FS=":"} {printf "%0.2f\n",$3}' /etc/passwd # 浮点数打印 保留两位小数
示例
匹配/etc/passwd文件中含有root字符串的所有行
awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd
匹配/etc/passwd文件中以yarn开头的所有行
awk 'BEGIN{FS=":"}/^yarn/{print $0}' /etc/passwd
示例
匹配/etc/passwd中第三个字段小于50的行
awk 'BEGIN{FS=":"}$3<50{print $0}' /etc/passwd
匹配第三个字段包含3个或3个以上的数字信息的所有行
awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' /etc/passwd # /[0-9]{3,}/ 固定写法
布尔运算符匹配
|| 或
&& 与
! 非
匹配/etc/passwd文件中包含hdfs或yarn的所有行信息
awk 'BEGIN{FS=":"}$1=="hdfs" || $1=="yarn" {print $0}' /etc/passwd
符号 | 含义 |
---|---|
+ | 加 |
* | 乘法 |
- | 减 |
/ | 除法 |
% | 取模 |
^或** | 乘方 |
++x | 先加1 |
x++ | 后加1 |
统计/etc/services中空白行的数量
awk '/^$/{sum++} END{print sum}' /etc/services # /^$/ 表示空白行
统计学生分数平均值
学生课程文件如下:
Allen 80 90 96 98
mike 93 98 92 91
zhang 78 76 87 92
awk 'BEGIN{printf "%-8s%-8s%-8s%-8s%-8s%-8s\n","name","math","english","chinese","history","avg"} {total=$2+$3+$4+$5;avg=total/4;printf "%-8s%-8d%-8d%-8d%-8d%-0.2f\n",$1,$2,$3,$4,$5,avg}' stu.txt
if(条件表达式)
动作1
else if
动作2
else
动作3
示例
只打印/etc/passwd/中第3个字段的数值在50-100范围内的行
awk 'BEGIN{FS=":"}{if($3<100 && $3>50) print($0)}' /etc/passwd
将命令写到文件中,并且执行 main.awk
BEGIN{FS=":"}{if($4<100 && $3>50) print($0)}
执行如下语句
awk -f main.awk /etc/passwd
while循环
do while
for循环,语法格式和c语言一致。
示例
计算1+2+3+…100的和,使用while、do while、for循环三种方式实现
# for循环
BEGIN{
for(i=0;i<=100;i++)
{
sum+=i
}
print sum
}
# while
BEGIN{
while(i<=100){
sum+=i
i++
}
print sum
}
#do while
BEGIN{
i=0
do{
sum+=i
i++
}while(i<=100)
print sum
}
函数名 | 解释 | 函数返回值 |
---|---|---|
length(str) | 字符串长度 | 整数长度值 |
index(str1,str2) | 在str1中查找str2的位置 | 返回位置索引,从1计数 |
tolower(str) | 转成小写 | 转化后的字符串 |
toupper(str) | 转成大写 | 转化后的字符串 |
substr(str,m,n) | 从str的m个字符开始,截取n位 | 截取后的子串 |
split(str,arr,fs) | 按照fs切割字符串,结果保存arr | 切割后子串的个数 |
match(str,RE) | 在str中按照RE查找,返回位置 | 返回索引位置 |
sub(RE,RepStr,str) | 在str中搜索符合RE的字符串,将其替换为RepStr,只替换一个 | 替换的个数 |
gsub(RE,RepStr,str) | 在str中搜索符合RE的字符串,将其替换为RepStr,替换所有 | 替换的个数 |
统计/etc/passwd中每行,每个字段的长度
BEGIN{
FS=":"
}
{ i=0
while(i<=NF)
{
if(i==NF){
printf "%d",$i
}
else{
printf "%d:",$i
}
i++
}
print ""
}
搜索字符串"I have s dream" 中出现"ea"子串的位置
# 使用index
awk 'BEGIN{str="I have s dream";location=index(str,"ea");print location}'
# 使用match
awk 'BEGIN{str="I have s dream";location=match(str,"ea");print location}'
字符串大小写转换
awk 'BEGIN{str="I have s dream";print tolower(str)}'
awk 'BEGIN{str="I have s dream";print toupper(str)}'
字符串分割
awk 'BEGIN{str="I have s dream";split(str,arr," ");for(i in arr) print arr[i]}'
截取子串
awk 'BEGIN{str="I have s dream"; print substr(str,4,5)}'
awk 'BEGIN{str="I have s dream"; print substr(str,4)}' # 第四位开始
字符串替换
# 将123替换为$ 符号。sub返回的个数,直接修改str
awk 'BEGIN{str="my 123 dream"; sub(/[0-9]+/,"$",str);print str}'
选项 | 解释 |
---|---|
-v | 参数传递 |
-f | 指定脚本文件 |
-F | 指定分隔符 |
-V | 查看awk版本号 |
num1=20
var="hello world"
awk -v num2="$num1" -v var1="$var" 'BEGIN{print num2,var1}'
定义
array=("Allen" "Mike" "Jick") # 空格分割
数组操作
# 打印元素
echo ${array[2]}
# 打印数组元素个数
echo ${#array[@]}
# 打印数组元素长度
echo ${#array[3]}
# 给元素复制
array[3]="Li"
# 删除元素
unset array[0] # 被删掉后 下标不变
# 分片访问
echo ${array[@]:1:3}
# 元素内容替换
${array[@]/e/E} # 只替换第一个e
${array[@]//e/E} # 替换所有的e
数组遍历
for a in ${array[@]}
do
echo $a
done
在awk中,使用数组时,不仅可以使用1,2,3…作为数组下标,还可以使用字符串作为下标
使用数字作为下标
str="Allen Jerry Mike"
split(str,array)
for(i=1;i<=length(array);i++)
print array[i]
使用字符串作为下标
array["var1"]="Jin"
array["var2"]="Hao"
array["var3"]="Fang"
for(a in array)
print array[a]
统计tcp链接状态个数
netstat -an | grep tcp | awk '{a[$6]++}END{for(i in a) print i,a[i]}'
计算横向数据总合,计算纵向数据总和
BEGIN{
printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","math","english","total"
}
{
total=$2+$3+$4
yuwen_sum+=$2 # 列之间的数累加
math_sum+=$3
enlish_sum+=$4
printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,total
}
END{
printf "%-10s%-10s%-10s%-10s%-10s\n","",yuwen_sum,math_sum,enlish_sum,""
}
getline可以实现同时读取两个文件进行操作
示例
A 1
B 2
C 3
A
C
BEGIN{
while(getline<"file1"){a[$1]=$2} # 将file1中加载到数组中
}
{
if($1 in a) print $0 # 如果file2中的$1在数组a中 则打印
}
END{
}