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
和正则表达式有了更深入的理解,并能够在实际工作中灵活运用它们,提高自己的文本处理和数据处理能力。不断尝试新的应用场景,将会发现更多的可能性。
超级会员免费看
16

被折叠的 条评论
为什么被折叠?



