13、AWK编程与正则表达式全解析

AWK编程与正则表达式全解析

1. AWK变量

AWK提供了许多内置变量来简化工作,以下是一些常见的内置变量:
| 变量名 | 作用 |
| ---- | ---- |
| FIELDWIDTHS | 指定字段宽度 |
| RS | 指定记录分隔符 |
| FS | 指定字段分隔符 |
| OFS | 指定输出分隔符,默认是空格 |
| ORS | 指定输出记录分隔符 |
| FILENAME | 保存正在处理的文件名 |
| NF | 保存当前处理行的字段数量 |
| FNR | 保存当前处理记录的编号 |
| IGNORECASE | 忽略字符大小写 |

例如,有如下文件:

John Doe 
15 back street 
(123) 455-3584 

Mokhtar Ebrahim 
10 Museum street 
(456) 352-3541

如果要打印姓名和电话号码,可以这样设置:

$ awk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' myfile

这里将 FS 设置为 \n RS 设置为空字符串,这样就能正确识别字段。

还可以使用 OFS ORS 来设置输出格式:

$ awk 'BEGIN{FS="\n"; RS=""; OFS="*"} {print $1,$3}' myfile

NR FNR 看起来相似,但有区别。 NR 保存处理的总行数, FNR 保存当前文件处理的记录数。例如:

$ awk 'BEGIN{FS="\n"}{print $1,"FNR="FNR}' myfile myfile

这里处理文件两次, FNR 每次处理都从1开始。而 NR 会保留整个处理过程的值:

$ awk 'BEGIN {FS="\n"} {print $1,"FNR="FNR,"NR="NR} END{print "Total lines: ",NR}' myfile myfile
2. 用户自定义变量

在AWK编程中,可以像其他编程语言一样定义自己的变量,但变量名不能以数字开头。例如:

$ awk '
BEGIN{
var="Welcome to AWk programming"
print var
}'

也可以定义数字变量并进行运算:

$ awk '
BEGIN{
var1=2
var2=3
var3=var1+var2
print var3
}'

还能进行字符串拼接:

$ awk '
BEGIN{
str1="Welcome "
str2=" To shell scripting"
str3=str1 str2
print str3
}'
3. 条件语句
3.1 if命令

假设有如下文件:

50
30
80
70
20
90

可以使用 if 语句过滤值:

$ awk '{if ($1 > 50) print $1}' myfile

也可以使用 else 子句:

$ awk '{
if ($1 > 50)
{
x = $1 * 2
print x
} else
{
x = $1 * 3
print x
}}' myfile

如果不使用花括号,可以用分号在同一行写多个语句:

$ awk '{if ($1 > 50) print $1 * 2;  else print $1 * 3}' myfile
3.2 while循环

当需要遍历每行的字段时,可以使用 while 循环。例如有文件:

321 524 124 
174 185 254 
195 273 345

使用 while 循环计算每行的平均值:

$ awk '{
total = 0
i = 1
while (i < 4)
{
total += $i
i++
}
mean = total / 3
print "Mean value:",mean
}' myfile
3.3 for循环

也可以使用 for 循环达到相同效果:

$ awk '{
total = 0
for (var = 1; var < 4; var++)
{
total += $var
}
mean = total / 3
print "Mean value:",mean
}' myfile
4. 输出格式化

之前使用 print 命令输出,当需要格式化输出时,比如打印用户名、UID和默认shell,可以使用 printf 函数指定列宽。
未格式化的输出:

$ awk ' BEGIN { FS=":" } { print $1,$3,$7 } ' /etc/passwd

使用 printf 格式化输出:

$ awk ' BEGIN { FS=":" }
> { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd

这里 %10s 表示字符串宽度为10, %4d 表示数字宽度为4, %17s 表示字符串宽度为17。

还可以添加表头信息:

$ awk 'BEGIN {FS=":" ;printf "%10s %4s %17s\n","Name","UID","Shell" }
> { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd

可以自定义函数添加颜色:

$ awk 'function green(s) {
> printf "\033[1;32m" s "\033[0m\n"
> }
> BEGIN {FS=":"; 
green("   Name:  UID:    Shell:") }
> { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd
5. 按UID进一步过滤用户

可以根据UID过滤用户,例如打印UID大于999的用户:

$ awk -F":" '$3 > 999 ' /etc/passwd

打印UID小于等于101的用户:

$ awk -F":" '$3 < 101 ' /etc/passwd
6. AWK控制文件

为了简化命令行和方便编辑,可以创建AWK控制文件。例如,对于 /etc/passwd 文件的格式化输出,可以创建如下文件 passwd.awk

function green(s) {  
    printf "\033[1;32m" s "\033[0m\n"  
}  
BEGIN {  
    FS=":"  
    green("   Name:   UID:       Shell:")  
}  
{  
    printf "%10s %4d %17s\n",$1,$3,$7  
} 

执行命令:

$ awk -f passwd.awk /etc/passwd
7. 内置函数

AWK有许多内置函数,如数学函数:
| 函数名 | 作用 |
| ---- | ---- |
| sin(x) | 正弦函数 |
| cos(x) | 余弦函数 |
| sqrt(x) | 平方根函数 |
| exp(x) | 指数函数 |
| log(x) | 对数函数 |
| rand() | 随机数函数 |

使用示例:

$ awk 'BEGIN{x=sqrt(5); print x}'

还有字符串处理函数,如 toupper

$ awk 'BEGIN{x = "welcome"; print toupper(x)}'
8. 正则表达式
8.1 正则表达式引擎

正则表达式是由正则表达式引擎解释以匹配特定文本的字符串,是一种高级搜索方式。正则表达式引擎是理解这些字符串并找到匹配文本的软件。

Linux中有两种正则表达式引擎:
- 基本正则表达式(BRE)引擎
- 扩展正则表达式(ERE)引擎

大多数Linux工具如 sed AWK 都支持这两种引擎, grep 使用 -E 选项可以支持ERE。

8.2 定义BRE模式

定义正则表达式模式示例:

$ echo "Welcome to shell scripting" | sed -n '/shell/p'
$ echo "Welcome to shell scripting" | awk '/shell/{print $0}'

正则表达式模式默认区分大小写。

如果要匹配特殊字符 .*[]^${}\+?|() ,需要用反斜杠转义。

8.3 常用BRE字符
  • 锚字符
  • ^ :匹配行的开头,例如:
$ echo "Welcome to shell scripting" | awk '/^Welcome/{print $0}'
  • $ :匹配行的结尾,例如:
$ echo "Welcome to shell scripting" | awk '/scripting$/{print $0}'

可以使用 ^ $ 来查找空行并过滤:

$ awk '!/^$/{print $0}' myfile
  • 点字符 . 匹配除换行符 \n 以外的任何字符,例如:
$ awk '/.sh/{print $0}' myfile
  • 字符类 :使用方括号 [] 指定要匹配的字符集合,例如:
$ awk '/[mbr]ash/{print $0}' myfile

可以使用 ^ 在方括号内取反:

$ awk '/[^br]ash/{print $0}' myfile

通过以上内容,我们可以看到AWK和正则表达式在文本处理中有着强大的功能,能够帮助我们高效地完成各种数据处理任务。无论是简单的数据筛选,还是复杂的文本格式化和匹配,都可以通过合理运用AWK和正则表达式来实现。希望大家通过不断实践,掌握这些工具,提升自己的文本处理能力。

9. 正则表达式的高级应用
9.1 组合使用正则表达式字符

我们可以将前面学到的正则表达式字符组合起来,实现更复杂的匹配。例如,要匹配以大写字母开头,中间包含 “shell”,并以 “ing” 结尾的行,可以这样做:

$ awk '/^[A-Z].*shell.*ing$/{print $0}' myfile

这个模式中, ^[A-Z] 表示行的开头是一个大写字母, .* 表示任意数量的任意字符, shell 是要匹配的特定字符串, .* 再次表示任意数量的任意字符, ing$ 表示行以 “ing” 结尾。

9.2 使用正则表达式进行替换

sed AWK 中,我们可以使用正则表达式进行替换操作。例如,将文件中所有的 “shell” 替换为 “bash”:

$ sed 's/shell/bash/g' myfile

这里的 s 表示替换命令, shell 是要被替换的字符串, bash 是替换后的字符串, g 表示全局替换,即替换一行中所有匹配的字符串。

AWK 中也可以实现类似的功能:

$ awk '{gsub(/shell/, "bash", $0); print $0}' myfile

gsub AWK 中的全局替换函数,第一个参数是要匹配的正则表达式,第二个参数是替换后的字符串,第三个参数是要进行替换操作的字段,这里是整行 $0

10. 正则表达式在数据验证中的应用

正则表达式在数据验证方面非常有用。例如,验证一个字符串是否是有效的电子邮件地址。一个简单的电子邮件地址验证正则表达式可以是:

$ awk '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/{print $0}' myfile

这个正则表达式的解释如下:
- ^ :表示行的开头。
- [a-zA-Z0-9._%+-]+ :表示一个或多个字母、数字、点、下划线、百分号、加号或减号,这是电子邮件地址的用户名部分。
- @ :表示电子邮件地址中的 “@” 符号。
- [a-zA-Z0-9.-]+ :表示一个或多个字母、数字、点或减号,这是域名的一部分。
- \. :表示一个点,需要用反斜杠转义。
- [a-zA-Z]{2,} :表示两个或更多的字母,这是域名的顶级域名部分。
- $ :表示行的结尾。

11. 正则表达式与 AWK 的结合案例

假设我们有一个日志文件,格式如下:

2023-10-01 12:30:00 [INFO] User John logged in.
2023-10-01 13:15:00 [ERROR] Database connection failed.
2023-10-02 09:45:00 [INFO] User Jane logged out.

我们想要提取所有的错误日志,可以使用 AWK 和正则表达式来实现:

$ awk '/\[ERROR\]/{print $0}' myfile

这里的正则表达式 \[ERROR\] 用于匹配包含 “[ERROR]” 的行,因为方括号在正则表达式中有特殊含义,所以需要用反斜杠转义。

如果我们想要进一步提取错误日志中的时间和错误信息,可以这样做:

$ awk '/\[ERROR\]/{split($1, date, "-"); split($2, time, ":"); print date[1] "/" date[2] "/" date[3], time[1] ":" time[2], $4, $5}' myfile

这个 AWK 脚本首先使用正则表达式匹配包含 “[ERROR]” 的行,然后使用 split 函数将日期和时间拆分成单独的部分,最后打印出日期、时间和错误信息。

12. 总结与展望

通过前面的学习,我们了解了 AWK 的各种功能,包括内置变量、用户自定义变量、条件语句、循环、输出格式化、控制文件和内置函数,以及正则表达式的基本概念、模式定义和高级应用。 AWK 和正则表达式在文本处理、数据筛选、格式化和验证等方面都有着强大的能力。

以下是一个总结表格:
| 工具/功能 | 描述 | 示例 |
| ---- | ---- | ---- |
| AWK 内置变量 | 简化工作,如 FS RS FNR 等 | $ awk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' myfile |
| 用户自定义变量 | 可定义字符串、数字等变量 | $ awk 'BEGIN{var="Welcome"; print var}' |
| 条件语句 | if while for 循环用于数据处理 | $ awk '{if ($1 > 50) print $1}' myfile |
| 输出格式化 | 使用 printf 函数指定列宽 | $ awk 'BEGIN { FS=":" } { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd |
| 正则表达式 | 高级搜索和匹配工具 | $ awk '/^[A-Z].*shell.*ing$/{print $0}' myfile |

未来,我们可以进一步探索 AWK 和正则表达式的更多应用场景,例如在大数据处理、自动化脚本编写等方面。同时,不断练习和实践,提高我们使用这些工具的熟练度和效率。

mermaid 格式流程图展示使用 AWK 和正则表达式处理文件的一般流程:

graph TD;
    A[开始] --> B[读取文件];
    B --> C{是否有更多行};
    C -- 是 --> D[应用 AWK 脚本和正则表达式];
    D --> E[处理当前行];
    E --> C;
    C -- 否 --> F[输出结果];
    F --> G[结束];

希望大家通过这篇文章,对 AWK 和正则表达式有了更深入的理解,并能够在实际工作中灵活运用它们,提高自己的文本处理和数据处理能力。不断尝试新的应用场景,将会发现更多的可能性。

内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化训练,到执行分类及结果优化的完整流程,并介绍了精度评价通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置结果后处理环节,充分利用ENVI Modeler进行自动化建模参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值