当我们在Unix/Linux中运行某写命令来读取或者编辑来自一个字符串或文件的文本时,我们大多数时候尝试过滤输出成给定的兴趣部分。这是正则表达式派上用处的地方。

正则表达式是什么?

一个正则表达式能够被定义成一个代表若干字符序列的字符串。正则表达式中一个最重要的事情是使你能够过滤命令或者文件的输出,编辑一个文本或者配置文件的一部分等。

特性和正则表达式

正则表达式由以下组成:

1、常规字符:诸如空白,下划线(_),A-Z,a-z, 0-9。

2、元字符:其被扩展成常规字符,它们包括:

  • (.):它匹配除了newline外任意单个字符。
  • (*):它匹配在它前面的字符0次或多次。
  • [ character(s) ]:它匹配在character(s)中指定的任何一个字符,也可以使用一个连字符(-)表示一个字符范围,例如:[a-f], [1-5]等。
  • ^:它匹配一个文件中的行首。
  • $:它匹配一个文件中的行尾。
  • \:它是一个转义字符。

为了过滤文本,必须使用一个文本过滤工具,如awk。你可以认为awk自身作为一种编程语言。但为了这里使用awk的范围,我们当它为一个简单的命令行过滤工具。

awk的一般语法是:

# awk 'script' filename

此处'script'是一个awk理解的命令集合并且对文件filename执行。

它通过读取文件中指定行运行,生成行的副本并且接着对这行执行脚本。在文件中所有行上重复这个动作。

'script'格式为'/pattern/ action',此处pattern是正则表达式,而action是当awk在一行中找到指定模式时它将做什么。

在Linux中如何使用Awk过滤工具

在以下示例中,我们强调在awk特性下以上讨论的元字符。

一个使用awk的简单示例:

以下示例由于没有给出模式,打印出在文件/etc/hosts中所有行。

[root@rockygu ~]# awk '//{print}' /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4


172.28.133.248  rockygu rockygu

使用带模式的awk

在以下示例中,给出了一个模式localhost,因此awk将在/etc/hosts文件中搜索包含localhost的行。

[root@rockygu ~]# awk '/localhost/{print}' /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4

使用在模式中有(.)通配符的awk

(.)在下列中将匹配loc, localhost, localnet。那意味着"*l单个字符c*"。

[root@rockygu ~]# awk '/l.c/{print}' /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4

使用在模式中有(*)通配符的awk

它将撇配包含localhost, localnet, lines, capable的字符串,如以下示例:

[root@rockygu ~]# awk '/l*c/{print}' /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4
172.28.133.248  rockygu rockygu

你也意识到了(*)尝试让你获取到它能够探测到最长可能的匹配。

看一下以下演示的情况,正则表达式t*t表示在一行中匹配字符串以字母t开头并且以t结束:

在/t*t/中(*)通配符使得awk选择了最长的匹配:

[root@rockygu ~]# echo "this is thirty, where you get the best good tutorials, how to's, guides, thirty." | awk '/t*t/{print}'
this is thirty, where you get the best good tutorials, how to's, guides, thirty.

使用带集合[character(s)]的awk

举例集合[r7],awk将匹配文件/etc/hosts中一行中包含r或7的所有字符串。

[root@rockygu ~]# awk  '/[r7]/{print}' /etc/hosts
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4
172.28.133.248  rockygu rockygu

接下来一个示例匹配ock跟在R或r之后的字符串:

[root@rockygu ~]# awk '/[Rr]ock/{print}' /etc/hosts
172.28.133.248  rockygu rockygu

指定一个范围内的字符

理解以下字符范围

  • [0-9]:表示单个数字
  • [a-z]:表示匹配单个小写字母
  • [A-Z]:表示匹配单个大写字母
  • [a-zA-z]:表示匹配单个字母
  • [a-zA-Z0-9]:表示匹配单个字母或数字

看以下以下示例:

[root@rockygu ~]# awk '/[0-9]/{print}' /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4
172.28.133.248  rockygu rockygu

在以上示例中,来自文件/etc/hosts中的所有行至少包含单个数字[0-9]。

使用带有(^)元字符的awk

在以下示例中,它匹配以所提供模式开头的所有行。

[root@rockygu ~]# awk '/^17/{print}' /etc/hosts
172.28.133.248  rockygu rockygu

使用带有($)元字符的awk

它匹配以所提供模式结尾的所有行:

[root@rockygu ~]# awk '/u$/{print}' /etc/hosts
172.28.133.248  rockygu rockygu

使用带有(\)转义字符的awk

它允许你在其之后按字符的字面接收这个字符。

在以下示例中,第一个命令打印出在一个文件中所有行,因为我想匹配一含有$25的行,但没有使用转义字符,第二条命令没有打印东西。

由于一个转义字符用于读取$的文字,第三条命令是正确的。

[root@rockygu ~]# awk '//{print}' deal.txt
$25.00
abc25.00
25.00
[root@rockygu ~]# awk '/$25.00/{print}' deal.txt
[root@rockygu ~]# awk '/\$25.00/{print}' deal.txt
$25.00
[root@rockygu ~]# awk '/\$25\.00/{print}' deal.txt
$25.00

结论

这是不awk命令行过滤工具的所有,以上示例是awk的基本操作。在awk命令系列的其它部分,我们进一步讨论如何使用awk复杂特性。