当前位置:网站首页>如何编写一个优雅的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,awkawk内置变量
| 变量 | 含义 |
|---|---|
| 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~shellgsub( 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,shellawk文件拆分
现实工作中,有这样一个需求,一个接口文件中,每行记录有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的帮助文档。
边栏推荐
猜你喜欢

Flink Distributed Cache 分布式缓存
![[Go through 8] Fully Connected Neural Network Video Notes](/img/0a/8b2510b5536621f402982feb0a01ef.png)
[Go through 8] Fully Connected Neural Network Video Notes

NodeJs接收上传文件并自定义保存路径

Error creating bean with name 'configDataContextRefresher' defined in class path resource

SQL(一) —— 增删改查

vscode+pytorch use experience record (personal record + irregular update)

Matplotlib(二)—— 子图

第三讲 Gradient Tutorial梯度下降与随机梯度下降

Using pip to install third-party libraries in Pycharm fails to install: "Non-zero exit code (2)" solution

第5讲 使用pytorch实现线性回归
随机推荐
2022 The 4th C.Easy Counting Problem (EGF+NTT)
【NFT开发】设计师无技术基础保姆级开发NFT教程在Opensea上全套开发一个NFT项目+构建Web3网站
MySql之索引
RDD和DataFrame和Dataset
【Over 16】Looking back at July
【过一下12】整整一星期没记录
Transformation 和 Action 常用算子
软件设计 实验四 桥接模式实验
day6-列表作业
学习总结week3_4类与对象
Using pip to install third-party libraries in Pycharm fails to install: "Non-zero exit code (2)" solution
redis persistence
Lecture 3 Gradient Tutorial Gradient Descent and Stochastic Gradient Descent
SQL(一) —— 增删改查
物理层的接口有哪几个方面的特性?各包含些什么内容?
day8字典作业
[Go through 8] Fully Connected Neural Network Video Notes
机器学习(一) —— 机器学习基础
【记一下1】2022年6月29日 哥和弟 双重痛苦
ES6基础语法