大家好,又见面了,我是你们的朋友全栈君。
awk是linux中处理文本的强大工具,或者说是一种专门处理字符串的语言,它有自己的编码格式。awk的强大之处还在于能生成强大的格式化报告。 awk的命令格式如下:
其中常用选项有 -F、-f等选项,后面会介绍。 例如
>awk -F: '{print $1}' file
表示把file文件中每行数据以“:”分割后,打印出第一个字段。下面详细介绍使用方式。 以下示例如不做说明,均用file文件为例,file文件中数据为:
The dog:There is a big dog and a little dog in the park
The cat:There is a big cat and a little cat in the park
The tiger:There is a big tiger and a litle tiger in the park
awk把分割后的数据字段自动分配给数据字段变量
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print $2}' file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
通过选项-F指定“:”为字段分隔符,把每行数据分为两段,然后输出第二个数据字段$2。
awk '{print $2}' file
如不显示指定字段分隔符,awk的默认字段分隔符为任意空白字符,包括制表符、空格符、换行符等。
上一个示例在program命令脚本中只使用了一个print命令,如果使用多个命令,则在每个命令之间加分号。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{$1="Description:"; print $0}' file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park
用冒号进行分割字段,然后把第一个字段替换为“Description:”,最后打印出整行数据。
如果program程序命令过多,可以单独放在一个文件中,然后从文件中读命令。还是以上面为例,把
{
$1="Description:"
print $0
}
单独放在一个文件script1中。再用awk处理脚本时,需要用选项 -f 指定脚本程序的位置。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: -f script1 file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park
awk默认每次读入一行数据,然后用脚本进行处理。如果想在处理文本之前预处理一些命令,可以用BEGIN关键字指定。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: 'BEGIN{print "开始处理..."}{print $2}' file
开始处理...
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
用END关键字在处理完所有数据后,再运行善后处理工作。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print $2} END{print "处理结束..."}' file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
处理结束...
变量又分为两种形式:awk内置的变量;用户自定义的变量。 【1】、内置变量 1. 与记录分隔符相关变量 – FS :输入字段分隔符 – OFS:输出字段分隔符 – RS:输入记录分割符 – ORS:输出字段分隔符 – FIELDWIDTHS:定义数据字段的宽度
FS用法
root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{FS=":"} {print $1, $2}' file
The dog There is a big dog and a little dog in the park
The cat There is a big cat and a little cat in the park
The tiger There is a big tiger and a litle tiger in the park
用FS指定字段分隔符为“:”,然后用“:”把每行数据分割为两段。
OFS用法 前面例子没有指定OFS,输出时默认数据字段之间用空格分开。
root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{FS=":"; OFS=">"} {print $1, $2}' file
The dog>There is a big dog and a little dog in the park
The cat>There is a big cat and a little cat in the park
The tiger>There is a big tiger and a litle tiger in the park
用FS指定输入字段分隔符“:”后,每行数据分为两个数据段,输出时,用OFS指定两个数据字段用“>”拼接。
RS和ORS用法 默认情况下RS和ORS设置为“\n”,表示输入数据流中的每一行作为一条记录,输出时每条记录之间也以“\n”进行分割。 下面以file2文件为例,fiel2文件中内容如下:
Tom is a student
and he is 20 years old
Bob is a teacher
and he is 40 years old
默认情况下,每行作为一条记录处理,但此种情况下,要把第一行和第二行作为一条记录处理,第三行和第四行作为一条记录处理。
root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{RS=""; ORS="\n"; FS="and"; OFS=","} {print $1, $2}' file2
Tom is a student
, he is 20 years old
Bob is a teacher
, he is 40 years old
2、与数据分割段有关的变量
ARGC 命令行参数个数
ARGV 命令行参数数组
FILENAME 当前输入文件的名字
IGNORECASE 如果为真,则进行忽略大小写的匹配
ARGIND 当前被处理文件的ARGV标志符
CONVFMT 数字转换格式 %.6g
ENVIRON UNIX环境变量
ERRNO UNIX系统错误消息
FIELDWIDTHS 输入字段宽度的空白分隔字符串
FNR 文件的当前记录数
NR 已处理的输入记录数
NF 数据文件中数据字段的个数
OFMT 数字的输出格式 %.6g
RSTART 被匹配函数匹配的字符串首
RLENGTH 被匹配函数匹配的字符串长度
下面介绍几个常用的 ARGC和ARGV ARGC表示命令行中的参数个数,ARGV是参数数组
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print ARGC, ARGV[0], ARGV[1]}' file
2 awk file
2 awk file
2 awk file
可见,每处理一行数据时,都是两个参数,第一个是awk本身,第二个是处理的文件名
NF NF表示数据文件中数据字段的个数,可以通过$NF获取最后一个数据字段
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print NF, $NF}' file
2 There is a big dog and a little dog in the park
2 There is a big cat and a little cat in the park
2 There is a big tiger and a litle tiger in the park
每行记录数据通过“:”分割都有两个数据字段。
NR和FNR FNR表示处理文件的当前记录号,NR表示所有处理文件已处理的输入记录个数。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print "NR="NR, "FNR="FNR, $2}' file file1
NR=1 FNR=1 There is a big dog and a little dog in the park
NR=2 FNR=2 There is a big cat and a little cat in the park
NR=3 FNR=3 There is a big tiger and a litle tiger in the park
NR=4 FNR=1 There is a big dog and a little dog in the forest
NR=5 FNR=2 There is a big cat and a little cat in the forest
NR=6 FNR=3 There is a big tiger and a litle tiger in the forest
注意,不要对NR和FNR加,例如,如果对NR加,加入NR等于5,实际就是取每条记录的第5个数据字段,实际没有这么多,只能取到空。
【2】、用户自定义变量 1、在脚本中使用用户自定义变量 建立一个script1的脚本,内容如下:
awk '
BEGIN{
FS = ":"
name = "lzj>"
}
{
$1 = name
print $0
}' file
运行该脚本 ./script
root@lzj-virtual-machine:/home/lzj/demo# ./script1
lzj> There is a big dog and a little dog in the park
lzj> There is a big cat and a little cat in the park
lzj> There is a big tiger and a litle tiger in the park
在脚本中直接定义了一个name变量,在脚本程序中可以直接引用该变量。注意在shell命令中,赋值语句“=”的前后是不能有空格的,但是在awk程序的内部是可以有的,因为awk是一种单独的编程语言。
2、在命令行中使用变量 首先定义一个script2脚本,其内容为:
BEGIN{
FS = ":"
}
{
print $n
}
脚本中有一个n的变量,在命令行中传入
root@lzj-virtual-machine:/home/lzj/demo# awk -f script2 n=2 file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
注意一个问题:在命令行中传入的参数,默认在BEGIN是不能获取的,例如 script2脚本改为如下,在BEGIN部分获取n的值:
BEGIN{
FS = ":"
print "请输出第二部分...", n
}
{
print $n
}
root@lzj-virtual-machine:/home/lzj/demo# awk -f script2 n=2 file
请输出第二部分...
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
运行命令,发现BEGIN部分的n值并没有打印出来。 但是如果用-v选项指定,并且把变量放在脚本代码之前,在BEGIN部分就可以访问了
root@lzj-virtual-machine:/home/lzj/demo# awk -v n=2 -f script2 file
请输出第二部分... 2
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
可以看到在BEGIN部分访问到了n的值2
1、数组赋值与查询 awk脚本中的数组有两种使用方式,一种是像其它高级语言一样,用数字下标来索引;另一种是用字典的key值来索引,key必须唯一。 新建script3脚本,内容为:
awk '
BEGIN{ arr["dog"] = "DOG" arr["cat"] = "CAT" print arr["cat"] }' file
root@lzj-virtual-machine:/home/lzj/demo# ./script3
CAT
2、数组递归 新建脚本script4,内容为:
echo "hello" | awk '
BEGIN{
arr["a"] = "A"
arr["b"] = "B"
arr["c"] = "C"
}
{
for(var in arr)
{
print arr[var]
}
}'
运行该脚本
root@lzj-virtual-machine:/home/lzj/demo# ./script4
A
B
C
注意,有时数组的顺序是不一致的。 3、删除数组元素 修改script4脚本,增加delete语句
echo "hello" | awk '
BEGIN{ arr["a"] = "A" arr["b"] = "B" arr["c"] = "C" } { delete arr["c"] for(var in arr) { print arr[var] } }'
运行脚本
root@lzj-virtual-machine:/home/lzj/demo# ./script4
A
B
可见删除了C元素。
在脚本中用正则匹配数据行时,正则表达式一定要放在脚本命令的左大括号之前,例如
$awk 'BEGIN{FS = ":"} /dog/{print $2}' file
匹配所有数据行中带dog字符的。
1、用~匹配特定数据字段 用正则表达式匹配指定的数据字段,匹配成功的,就是脚本要处理的数据。
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 ~ /^The cat$/{print $2}' file
There is a big cat and a little cat in the park
数据行中的第一个数据字段满足以The开头,cat结尾的数据行,执行后面的脚本。示例可知只有一条数据行满足记录。
当然也可以通过匹配的否定形式(!~)来排除数据行
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 !~ /dog/{print $2}' file
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
2、使用数学表达式 可以在匹配数据行时用数学表达式。 以处理file3文件为例,文件内容为:
1:This is 1 line
2:This is 2 line
3:This is 3 line
4:This is 4 line
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 % 2 == 0{print $2}' file3
This is 2 line
This is 4 line
匹配第一个数据字段除2余0的数据行记录。 数学表达式中的+、-、*、/、^(平方)等都可以应用。 另外数学表达式不仅可以用在匹配部分,还可以用在BEGIN、program命令脚本、END部分。 常用的数学比较大小的表达式如下:
注意,如果要比较文本的话,只能用“==”进行比较
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 == "The cat"{print $2}' file
There is a big cat and a little cat in the park
1、if结构 格式为:
if(condition){
statement1
statement2
.....
}else
{
statement3
......
}
新建script5脚本,如果,每个数据行包括两个数据字段就执行if条件。
awk -F: '{ if(NF == 2) { print $1 print $2 }else { pring NF } }' file
运行脚本
root@lzj-virtual-machine:/home/lzj/demo# ./script5
The dog
There is a big dog and a little dog in the park
The cat
There is a big cat and a little cat in the park
The tiger
There is a big tiger and a litle tiger in the park
2、while循环结构 格式
while(condition)
{
statement1
statement2
...
}
新建script6脚本,计算10以内的奇数和
echo "hello" | awk '
{
total = 0
i = 1
while(i < 10)
{
if(i % 2 == 0)
{
i++
continue
}
total = total + i
i++
}
print "total=", total
}'
运行脚本
root@lzj-virtual-machine:/home/lzj/demo# ./script6
total= 45
3、for循环 结构
for(variable addignment; condition; iteration peocess)
{
statement1
statement2
...
}
修改上一示例,改为for循环结构,求10以内奇数的和
echo "hello" | awk '
{
total = 0
for(i=1; i<10; i++)
{
if(i % 2 == 0)
{
continue
}
total = total + i
}
print "total=", total
}'
结果与上一示例相同。 注意:在awk的for和while循环中也支持breake、continue。
数学函数
字符串函数
位操作函数
时间函数
用户自定义函数一定要放在调用之前进行定义 格式
function function_name([variable])
{ statement1 statement2 .... }
例如处理file4文件,内容如下,只提取其中姓名和电话
Bob NanjingRoad 6623432
Terry BeijingRoad 6689764
Lily GuangzRoad 6623678
新建脚本script7,内容如下
awk '
function fshow()
{
printf "%-5s : %s\n", $1, $3
}
BEGIN{
print "开始处理..."
}
{
fshow()
}' file4
运行脚本如下
root@lzj-virtual-machine:/home/lzj/demo# ./script7
开始处理...
Bob : 6623432
Terry : 6689764
Lily : 6623678
注意: printf的用法通C语言一样; 在脚本中BEGIN后面一定要紧跟“{”,否则会出错。
参考:linux脚本教程宝典
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157379.html原文链接:https://javaforall.cn