AWK与正则表达式:数据处理与文本匹配的强大工具
1. AWK命令基础
AWK是一个强大的数据处理工具,可用于从文件中过滤和显示内容,尤其适用于处理大文件。我们可以先打印整个文件,以熟悉命令语法,之后再将控制信息添加到AWK文件中,简化命令行操作。
-
打印整个文件
:使用以下命令可以打印
/etc/passwd文件的所有行:
$ awk ' { print } ' /etc/passwd
这等价于使用
$0
变量和
print
语句:
$ awk ' { print $0 }' /etc/passwd
-
AWK内置变量
:AWK提供了一些内置变量用于提取数据,如下表所示:
| 变量 | 含义 |
| ---- | ---- |
|$0| 整行内容 |
|$1| 第一个字段 |
|$2| 第二个字段 |
|$3| 第三个字段 |
| … | … |
2. 指定字段分隔符
在处理
/etc/passwd
文件时,需指定字段分隔符为冒号,因为AWK的默认分隔符是空格、制表符或换行符。指定输入分隔符有两种方式:
-
使用
-F
选项
:简单易用,适用于不需要额外头部信息的情况。
$ awk -F":" '{ print $1 }' /etc/passwd
-
在
BEGIN块中设置 :当需要使用BEGIN块显示头部信息时很有用。
$ awk ' BEGIN { FS=":" } { print $1 } ' /etc/passwd
3.
BEGIN
、
END
代码块
-
BEGIN块 :用于初始化操作,代码只执行一次。 -
END块 :常用于显示汇总数据,代码也只执行一次,而主代码块会对每一行进行处理。例如,打印passwd文件的总行数:
$ awk ' BEGIN { FS=":" } { print $1 } END { print NR } ' /etc/passwd
其中,
NR
是AWK的内部变量,用于记录已处理的行数。我们还可以添加额外文本注释汇总数据,并利用单引号将代码跨多行书写:
$ awk ' BEGIN { FS=":" }
> { print $1 }
> END { print "Total:",NR } ' /etc/passwd
若要显示每行的行号和最终总行数,可使用以下命令:
$ awk ' BEGIN { FS=":" }
> { print NR,$1 }
> END { print "Total:",NR } ' /etc/passwd
4. 单独使用
END
块
可以单独使用
END
块,模拟
wc -l
命令统计文件行数:
$ awk ' END { print NR }' /etc/passwd
5. 选择特定行
- 打印前五行:
$ awk ' NR < 6 ' /etc/passwd
- 打印第8行到第12行:
$ awk ' NR==8,NR==12 ' /etc/passwd
6. 使用正则表达式匹配文本
使用正则表达式可以匹配行中的文本,例如查找以
bash
结尾的行:
$ awk ' /bash$/ ' /etc/passwd
使用正则表达式模式时,需用两个斜杠将模式括起来,如
/bash$/
。
7. 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
若要打印姓名和电话号码,可设置
FS
为换行符
\n
,
RS
为空字符串:
$ awk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' myfile
还可以使用
OFS
和
ORS
设置输出格式:
$ awk 'BEGIN{FS="\n"; RS=""; OFS="*"} {print $1,$3}' myfile
8.
NR
与
FNR
的区别
NR
记录已处理的总行数,
FNR
记录当前文件的记录号。通过以下示例可以看出区别:
$ awk 'BEGIN{FS="\n"}{print $1,"FNR="FNR}' myfile myfile
$ awk 'BEGIN {FS="\n"} {print $1,"FNR="FNR,"NR="NR} END{print "Total lines: ",NR}' myfile myfile
在处理多个文件时,
FNR
会为每个文件重新从1开始计数,而
NR
会持续累加。
9. 用户自定义变量
可以像在其他编程语言中一样,在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
}'
10. 条件语句
-
if语句 :用于过滤文件中的值。例如,过滤出大于50的值:
$ 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
-
while循环 :用于遍历每行的字段。例如,计算每行字段的平均值:
$ awk '{
total = 0
i = 1
while (i < 4)
{
total += $i
i++
}
mean = total / 3
print "Mean value:",mean
}' myfile
-
for循环 :同样可用于遍历值,实现与while循环相同的结果:
$ awk '{
total = 0
for (var = 1; var < 4; var++)
{
total += $var
}
mean = total / 3
print "Mean value:",mean
}' myfile
11. 输出格式化
使用
print
命令输出时,可能会出现列不对齐的问题。可以使用
printf
函数指定列宽,改善输出格式。例如:
$ awk ' BEGIN { FS=":" }
> { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd
还可以添加头部信息:
$ awk 'BEGIN {FS=":" ;printf "%10s %4s %17s\n","Name","UID","Shell" }
> { printf "%10s %4d %17s\n",$1,$3,$7 } ' /etc/passwd
通过自定义函数,可以在AWK中添加颜色输出:
$ 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
12. 根据UID进一步过滤用户
可以根据用户的UID过滤用户。例如,打印UID大于999的标准用户:
$ awk -F":" '$3 > 999 ' /etc/passwd
打印UID小于等于101的用户:
$ awk -F":" '$3 < 101 ' /etc/passwd
13. AWK控制文件
为了简化命令行并方便后续编辑,可以创建AWK控制文件。例如,将格式化
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
14. 内置函数
AWK提供了许多内置函数,包括数学函数和字符串处理函数。例如:
$ awk 'BEGIN{x=sqrt(5); print x}'
$ awk 'BEGIN{x = "welcome"; print toupper(x)}'
15. 正则表达式基础
正则表达式是一种强大的文本匹配工具,可用于在文件中进行高级搜索。正则表达式由正则表达式引擎解释,用于匹配特定文本。
- 正则表达式引擎 :Linux中有两种主要的正则表达式引擎:
- 基本正则表达式(BRE)引擎
- 扩展正则表达式(ERE)引擎
大多数Linux二进制工具(如
sed
和
AWK
)都支持这两种引擎,
grep
需要使用
-E
选项来支持ERE,等同于使用
egrep
。
以下是正则表达式相关操作的流程:
graph TD;
A[开始] --> B[选择正则表达式引擎];
B --> C{选择BRE还是ERE};
C -- BRE --> D[定义BRE模式];
C -- ERE --> E[定义ERE模式];
D --> F[使用sed或AWK进行匹配];
E --> F;
F --> G[输出匹配结果];
G --> H[结束];
接下来我们将详细介绍如何定义BRE和ERE模式,以及如何使用
grep
进行文本匹配。通过掌握正则表达式,我们可以充分发挥
sed
和
AWK
的强大功能,更高效地处理文本数据。
16. 定义 BRE 模式
基本正则表达式(BRE)是正则表达式的基础形式,在很多 Linux 工具中都有广泛应用。以下是一些常见的 BRE 模式及其示例:
- 字符匹配 :
-
.:匹配任意单个字符。例如,a.c可以匹配abc、adc等。 -
[]:匹配方括号内指定的任意一个字符。例如,[abc]可以匹配a、b或c。 -
[^ ]:匹配不在方括号内的任意一个字符。例如,[^abc]可以匹配除a、b、c之外的任意字符。 -
重复匹配 :
-
*:匹配前面的字符零次或多次。例如,ab*c可以匹配ac、abc、abbbc等。 -
\{n\}:匹配前面的字符恰好n次。例如,a\{3\}只能匹配aaa。 -
\{n,\}:匹配前面的字符至少n次。例如,a\{2,\}可以匹配aa、aaa等。 -
\{n,m\}:匹配前面的字符至少n次,最多m次。例如,a\{1,3\}可以匹配a、aa或aaa。 -
位置匹配 :
-
^:匹配行的开头。例如,^abc只匹配以abc开头的行。 -
$:匹配行的结尾。例如,abc$只匹配以abc结尾的行。
以下是一个使用 BRE 模式在
AWK
中匹配以
root
开头的行的示例:
$ awk '/^root/ { print }' /etc/passwd
17. 定义 ERE 模式
扩展正则表达式(ERE)在 BRE 的基础上进行了扩展,提供了更强大的匹配功能。以下是一些 ERE 特有的模式及其示例:
- 重复匹配扩展 :
-
+:匹配前面的字符一次或多次。例如,ab+c可以匹配abc、abbbc等,但不能匹配ac。 -
?:匹配前面的字符零次或一次。例如,ab?c可以匹配ac或abc。 -
():用于分组。例如,(ab)+可以匹配ab、abab等。 -
或匹配 :
-
|:表示或关系。例如,a|b可以匹配a或b。
以下是一个使用 ERE 模式在
AWK
中匹配以
root
或
bin
开头的行的示例:
$ awk -E '/^(root|bin)/ { print }' /etc/passwd
18. 使用
grep
进行文本匹配
grep
是一个常用的文本搜索工具,支持 BRE 和 ERE 模式。以下是一些常见的
grep
使用示例:
- 使用 BRE 模式 :
$ grep '^root' /etc/passwd
该命令将搜索
/etc/passwd
文件中以
root
开头的行。
- 使用 ERE 模式 :
$ grep -E '^(root|bin)' /etc/passwd
该命令将搜索
/etc/passwd
文件中以
root
或
bin
开头的行。
19. 综合应用示例
以下是一个综合应用
AWK
和正则表达式的示例,用于从
/etc/passwd
文件中筛选出 UID 大于 1000 且默认 shell 为
/bin/bash
的用户:
$ awk -F":" '$3 > 1000 && /\/bin\/bash$/ { print $1 }' /etc/passwd
该命令的执行步骤如下:
1. 使用
-F":"
指定字段分隔符为冒号。
2.
$3 > 1000
筛选出 UID 大于 1000 的行。
3.
/\/bin\/bash$/
使用正则表达式筛选出默认 shell 为
/bin/bash
的行。
4.
{ print $1 }
打印符合条件的用户名。
20. 总结
通过本文的介绍,我们了解了
AWK
命令的强大功能,包括文件内容的显示与过滤、变量的使用、条件语句和循环的应用、输出格式化等。同时,我们也学习了正则表达式的基础知识,包括 BRE 和 ERE 模式的定义以及如何使用
grep
进行文本匹配。
AWK
和正则表达式的结合可以让我们更高效地处理和分析文本数据。在实际应用中,我们可以根据具体需求灵活运用这些工具和技术,提高工作效率。
以下是本文主要内容的总结表格:
| 主题 | 主要内容 |
| ---- | ---- |
| AWK 命令基础 | 打印文件内容、使用内置变量提取数据 |
| 指定字段分隔符 | 使用
-F
选项和
BEGIN
块设置分隔符 |
|
BEGIN
、
END
代码块 | 用于初始化和汇总数据 |
| 选择特定行 | 使用行号和正则表达式选择行 |
| AWK 变量 | 内置变量和用户自定义变量 |
| 条件语句 |
if
、
while
和
for
循环 |
| 输出格式化 | 使用
printf
函数和自定义函数 |
| 根据 UID 过滤用户 | 根据 UID 范围筛选用户 |
| AWK 控制文件 | 简化命令行和方便编辑 |
| 内置函数 | 数学函数和字符串处理函数 |
| 正则表达式 | BRE 和 ERE 模式、
grep
的使用 |
希望本文能帮助你更好地掌握
AWK
和正则表达式的使用,在实际工作中发挥它们的强大威力。
超级会员免费看
102

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



