当前位置: 首页 > article >正文

shell编程-awk使用系统学习

awk的基本结构:

awk options ' BEGIN{ print "start" } pattern { commands } END{ print "end" } file

awk语法主要包含三个模块:BEGIN语句块、END语句块和能够使用 模式匹配的通用语句块。这3个部分是可选的,它们中任何一个部分都 可以不出现在脚本中。脚本通常会被包含在单引号或双引号中。

工作原理:

1. 执行BEGIN { commands } 语句块中的语句。

2. 从文件或stdin中读取一行,然后执行pattern { commands }。

     重复这个过程,直到文件全部被读取完毕。

3. 当读至输入流(input stream)末尾时,执行END { commands } 语 句块。

BEGIN语句块:

BENGIN语句块是再awk开始从输入流读取行之前被执行,只会执行一次。是可选语句块。

诸如变量初始化、打印输出表格的表头等语句通常都可以写 入BEGIN语句块中

END语句块 

 与BEGIN语句块类似,只会执行一次,是在awk从输入流读取完所有的行之后立即被执行。也是可选数据库。

像打印所有行的分析结果这类汇总信息,都是 在END语句块中实现的常见任务

Pattern块

pattern语句块用于匹配输入数据的模式。如果省略,则 awk 将对所有行进行操作。
这个语句块同样是可 选的。如果不提供该语句块,则默认执行{ print },即打印每一个读 取到的行。

awk对于读取的每一行,都会执行这个语句块。

每读取一行时,它就会检查该行和提供的样式是否匹配。样式本身可以 是正则表达式、条件以及行匹配范围等。如果当前行匹配该样式,则执 行{ }中的语句。 样式是可选的。如果没有提供样式,那么它就会默认所有的行都是匹配 的,并执行{ }中的语句。

{commands}块

awk脚本中的通用命令,是最重要的块。对与前面模式匹配的进行操作,若是没有pattern则,commands对于读入的每一行执行操作。

options

  • -F <分隔符> 或 --field-separator=<分隔符>: 指定输入字段的分隔符,默认是空格。使用这个选项可以指定不同于默认分隔符的字段分隔符。

  • -v <变量名>=<值>: 设置 awk 内部的变量值。可以使用该选项将外部值传递给 awk 脚本中的变量。

  • -f <脚本文件>: 指定一个包含 awk 脚本的文件。这样可以在文件中编写较大的 awk 脚本,然后通过 -f 选项将其加载。

  • -V 或 --version: 显示 awk 的版本信息。

  • -h 或 --help: 显示 awk 的帮助信息,包括选项和用法示例。

注意点

通常将变量初始化语句(如var=0)以及打印文件头部的 语句放入BEGIN语句块中。若是放在pattern { commands }语句块中则每行都会被初始化或者打印

awk特殊变量

 NR:表示记录数量(number of records),在执行过程中对应 于当前行号。

NF:表示字段数量(number of fields),在执行过程中对应于 当前行的字段数。

$0:这个变量包含执行过程中当前行的文本内容。

$1:这个变量包含第一个字段的文本内容。

$2:这个变量包含第二个字段的文本内容。

$NF:一行中最后一个字段。用print $NF打印一行中最后一个字段,用 $(NF-1)打印 倒数第二个字段

使用例子:

[yuxuanxuan@bastion3 ~]$ echo -e "line1 f2 f3 \nline2 f4 f5 \nline3 f6 f7"|awk '{print "Line_No:"NR,"fields num:"NF,"$0="$0,"$1="$1,"$2="$2,"$3="$NF}'
Line_No:1 fields num:3 $0=line1 f2 f3  $1=line1 $2=f2 $3=f3
Line_No:2 fields num:3 $0=line2 f4 f5  $1=line2 $2=f4 $3=f5
Line_No:3 fields num:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7

echo输出三行文本: echo -e "line1 f2 f3 \nline2 f4 f5 \nline3 f6 f7"

 awk的pattern部分是{print "Line_No:"NR,"fields num:"NF,"$0="$0,"$1="$1,"$2="$2,"$3="$NF},对于每行文本都会执行

双引号与单引号的使用

1,awk中print语句中,双引号是被当作拼接使用的:

echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"-"var2"-"var3 ; }'

打印:v1-v2-v3

上面的{}类似一个循环体,对文件中的每一行进行迭代,但是echo只输入一行,所以只打印一次

2,脚本通常被包含在单引号或者双引号中,看具体使用场景而定

例如

[sss@git2 shelltest]$  awk 'BEGIN { i=0 } { i++ } END{ print i}' testfile.txt
5
[sss@git2 shelltest]$  awk "BEGIN { i=0 } { i++ } END{ print i}" testfile.txt
5
[sss@git2 shelltest]$

注意:要是脚本中有awk特殊变量的使用,只能使用单引号

awk -F' +' "{if ($2 > 90){print $1 '\tgood'}else{print $1 '\tbad'} }END{print 'total:',NR}" test.txt

运行报错:

awk: cmd. line:1: {if ( > 90){print  '\tgood'}else{print  '\tbad'} }END{print 'total:',NR}
awk: cmd. line:1:       ^ syntax error
awk: cmd. line:1: {if ( > 90){print  '\tgood'}else{print  '\tbad'} }END{print 'total:',NR}
awk: cmd. line:1:                    ^ invalid char ''' in expression

因为其中的双引号中$2会被误认为shell中的变量进行解析,另外'\tgood' '\tbad'也不会被正确解析。需要使用单引号括起,改为如下的形式即可:

awk -F' +' '{if ($2 > 90){print $1 "\tgood"}else{print $1 "\tbad"} }END{print "total:",NR}' test.txt

awk中的if使用

if 语句块

if (表达式 )  {
  语句;语句;...
}

属于操作块,if语句若是单个,则不需要{}

awk '{if (condition) {statement1;statement2;statement3;....} }' [input_file]

awk '{if(NR>=2 && NR<=3) print $1}' testfile.txt

选取2,3行打印出来

if else语句块

 awk '{ if (condition) {statement1;statement2;statement3;....} else {statement1;statement2;statement3;....} }' [input_file]

if else-if语句块

if(condition1){

command1

}

else if(condition2) {

command2

}

else if(condition3) {

command3

}

.

.

.

else{

commandN

}

awk的三重运算符

条件为真,conmand1语句块将会执行,条件为假,command2将会执行。

(condition) ? Command1:Command2

 例子:

awk '{print ($3 <=20)? "Age less than 20: " $2: "Age over 20: " $2}' students.txt

awk  正则匹配

 ~,!~表示匹配或者不匹配

// 中是模式。

例如:

第二列匹配正则/th/则执行打印 {print $2,$4}

 awk '$2 ~ /th/ {print $2,$4}' log.txt

 log.txt中每一列只要有匹配re的就打印所有行内容

 awk '/re/ ' log.txt

awk for循环的使用

第一种循环体:for (初始化; 条件; 迭代) { # 循环体 }

for (初始化; 条件; 迭代) { # 循环体 }

初始化:初始化一个计数器或变量,通常在循环开始之前执行。

条件:在每次迭代之前检查的条件,如果条件为真,循环会继续执行;如果条件为假,循环会终止。

迭代:在每次迭代之后执行的操作,通常用于递增或递减计数器。 

例如,如下例子是依次打印testfile.txt中的每一行的所有字段,NF表示字段数量

awk '{ for(i=1; i<=NF; i++) print $i }' testfile.txt

第二种循环体:for(元素 in 元素列表){#循环体} 

比如以下代码: 

awk 'BEGIN {
	#awk加注释,跟shell一样,#号开头就可以了。	
	#我们定义一个names的数组,键存的是名字, 值是年龄。
	names["Alice"] = 25
	names["Bob"] = 30
	names["Carol"] = 28
	
	#我们可以循环遍历names数组,并打印元素
	for (name in names) {
		printf("%s的年龄是%d岁\n", name, names[name])
	}
}'

打印

Carol的年龄是28岁
Bob的年龄是30岁
Alice的年龄是25岁


http://www.kler.cn/a/518314.html

相关文章:

  • 如何部署 Flask 应用程序到生产环境?
  • 人工智能的未来:AGI、ACI与ASI的探索
  • Kimi k1.5:基于大语言模型的多模态强化学习训练技术报告
  • Base64编码解密:解码下载邀请
  • 使用 Tauri 开发桌面应用程序:新一代的轻量解决方案
  • 编写python 后端 vscode 安装插件大全
  • DDD架构实战第七讲总结:分层模型和代码组织
  • Redis内存面试与分析
  • 如何在 Windows 上安装 MySQL(保姆级教程2024版)
  • RocketMQ底层哪里用了Netty
  • 51单片机(四)定时器
  • AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布
  • 25美赛ABCDEF题详细建模过程+可视化图表+参考论文+写作模版+数据预处理
  • 「全网最细 + 实战源码案例」设计模式——抽象工厂模式
  • 利用大语言模型(LLM)增强软件测试自动化的最佳实践
  • 【韩顺平Java笔记】第8章:面向对象编程(中级部分)【354-358】
  • AI模型提示词(prompt)优化-实战(一)
  • css遇到的一些问题
  • Kafka生产者ACK参数与同步复制
  • 简洁明了:介绍大模型的基本概念(大模型和小模型、模型分类、发展历程、泛化和微调)