当前位置:网站首页>如何编写一个优雅的Shell脚本(三)
如何编写一个优雅的Shell脚本(三)
2022-08-05 05:14:00 【IT_xhf】
简介
awk是shell脚本里面文本处理神奇,它虽然没有像Java、C、C++这些高级语言那样开发服务类型的应用程序,但是它擅长的是处理文件。本博客主要是对自己以往工作中使用awk的一个总结,不会对awk的语法做一个全面介绍,如果像更深入的了解AWK,推荐大家一本awk的书籍《awk与sed》。但是会对工作用到的awk一些功能进行介绍。废话不少说,进入正题吧。
awk语法
awk其实就是将文件一行一行的遍历处理,每一行代码处理文本中的一行记录,读取的顺序。
- 按照文件的参数传入顺序进行读取
- 每一个文件都是从第一行到最后以后顺序读取
一个AWK程序的基本组成部分,包括如下
- BEGIN: 相当于Java中类的构造函数,程序启动第一个运行的块
- 主体部分:主体部分通过两个中括号括起来,一个awk程序里面可以有多个中括号,多个中括号括起来会重复便利参数文件里面的内容进行处理(这种功能一半用的比较少)。
awk [option] 'BEGIN{ } [partition]{ }END{ }' 参数文件列表
awk -f awk脚本文件 参数文件列表
option ,项目中使用较多的选项有 -f -F -v。
-f选项是将awk的程序写在一个文件里面,通过-f参数将文件里面的内容当作awk脚本程序。
$ cat test.data
1,hello,awk
2,hello,shell
$ cat test.awk
BEGIN{
print "begin" }
{
print $0
}
END {
print "end" }
$ awk -f test.awk test.data
begin
1,hello,awk
2,hello,shell
end
-F 制定解析文件的分隔符,可以多个字符。默认分隔符为空格和制表符。也可以用FS内置变量来实现。
$ awk -F"," '{print $2}' test.data
hello
hello
-v,可以将shell脚本里面的变量传送到awk中。
$ shellVar="awk"
$ awk -F"," -v shellVar=$shellVar '{print shellVar}' test.data
awk
awk
$ awk -F"," -v shellVar=$shellVar '$3==shellVar{print $0}' test.data
1,hello,awk
awk内置变量
变量 | 含义 |
---|---|
ARGC | 命令行参数个数 |
ARGV | 命令行参数数组 |
FILENAME | 当前输入文件名 |
FNR | 当前文件中的记录号 |
FS | 输入域分隔符,默认为一个空格 |
RS | 输入记录分隔符 |
NF | 当前记录里域个数 |
NR | 到目前为止记录数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
awk内置函数
- split( String, A, [Ere] )
将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。
$ awk '{ split($0,a,","); print a[1],a[2],a[3] }' test.data
1 hello awk
2 hello shell
# 以上输出数组a,split返回的数组下标以1开始。我们也可以通过OFS变量制定输出分隔符
$ awk 'BEGIN {OFS="~"}{ split($0,a,","); print a[1],a[2],a[3] }' test.data
1~hello~awk
2~hello~shell
gsub( Ere, Repl, [ In ] )
除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行。sub( Ere, Repl, [ In ] )
用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与 Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。
$ awk -F"," '{a=$3; gsub("awk","我是被替换的", $3); print a, $3}' test.data
awk 我是被替换的
shell shell
- match( String, Ere )
在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。
$ awk -F"," '{match($3,'/^[a-z]{
2}k$/'); print RSTART, RLENGTH}' test.data
1 3
0 -1
# 可以用这个函数,通过正则表达式去匹配字符串里面的子字符串
$ awk '{ value=$1 while(match(value,/\w+,/) > 0) { print substr(value,RSTART,RLENGTH-1); value=substr(value,RLENGTH+1); } print value }' test.data
1
hello
awk
2
hello
shell
- tolower( String )
返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 - toupper( String )
返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。
awk实践
awk文件关联
awk可以像SQL一样,实现两个和多个文件关联。
有如下两个文件
$ cat test2.data
1,测试关联
$ cat test.data
1,hello,awk
2,hello,shell
# test.data 左关联test2.data
$ awk -F"," '{if (FILENAME=="test2.data") { a[$1]=$2 } else { print $0, a[$1] }}' test2.data test.data
1,hello,awk 测试关联
2,hello,shell
awk文件拆分
现实工作中,有这样一个需求,一个接口文件中,每行记录有1个或多个字段包含了一个数组,我们需要将数组进行拆分成一条条的记录。
$ cat test3.data
1,test1,数组11&数组12
2,test2,数组21&数组22
# 拆分后的结果
$ awk -F"," '{ split($3,a,"&"); # 将第三个字段进行拆分到a数组 for (i in a) { print $1,$2,a[i] } }' test3.data
1 test1 数组11
1 test1 数组12
2 test2 数组21
2 test2 数组22
总结
本文主要是针对过往一些工作中使用到shell脚本里面的awk命令进行总结,总结的内容属于awk的冰山一角。如果awk吸引到你,你可以去系统的了解以下awk。建议看看《awk与sed》这本书,或者再linux系统中使用 man命令获取awk的帮助文档。
边栏推荐
猜你喜欢
随机推荐
学习总结week2_1
redis persistence
Flink accumulator Counter 累加器 和 计数器
机器学习(一) —— 机器学习基础
第三讲 Gradient Tutorial梯度下降与随机梯度下降
[Remember 1] June 29, 2022 Brother and brother double pain
flink部署操作-flink on yarn集群安装部署
flink基本原理及应用场景分析
转正菜鸟前进中的经验(废话)之谈 持续更新中... ...
day10-字符串作业
【过一下12】整整一星期没记录
周末作业-循环练习题(2)
SQL(二) —— join窗口函数视图
【技能】长期更新
HQL statement execution process
学习总结week2_5
Wise Force Deleter强制删除工具
Calling Matlab configuration in pycharm: No module named 'matlab.engine'; 'matlab' is not a package
Flink EventTime和Watermarks案例分析
redis 缓存清除策略