正则表达式(Regular Expression,通常简称为 regex 或 RE)是一种表达方式,可以用它来查找匹配特定准则的文本。在许多编程语言中都有用到正则表达式,常用它来实现一些复杂的匹配。这里简单介绍一下 shell 中常用到的一些正则表达式。

一、什么是正则表达式

  正则表达式是对字符串进行操作的一种逻辑公式,即用事先定义好的的一些特定字符以及这些特定字符的组合,组成一个有一定规则的字符串(Regular Expression),使用这个有一定规则的字符串来表达对字符串的一种过滤逻辑。正则表达式被广泛应用于Linux和许多其他编程语言中,而且不论在哪里,其基本原理都是一样的。

  从根本上来看,正则表达式是由两个基本组成部分所建立:一般字符与特殊字符。一般字符是指没有任何特殊意义的字符;特殊字符,常称为元字符 (metacharacter),或 meta 字符,顾名思义,就是指那些有特殊意义的字符,当然在某些情况下,特殊字符也可被视为一般字符(使用转义符 \ 进行转义)。

  POSIX 有两种风格的正则表达式,基本正则表达式(BRE)和扩展正则表达式(ERE)。这两种风格的正则表达式在一些字符含义上有细微的差距。以常用的 grep 指令来说,grep 指令默认支持的是 BRE,若要使用 ERE 进行匹配,可以使用 -E 选项,接下来的例子中均使用 grep 指令来演示正则表达式的使用。

二、基本正则表达式

2.1 常用 meta 字符列表 

   字符         BRE/ERE   含义
  . BRE&ERE 匹配任意单个字符(除字符串结束符 NUL)
  ^ BRE&ERE 匹配行首,如  ^abc,匹配以 abc 开头的字符串
  $ BRE&ERE 匹配行尾,如  abc$,匹配以 abc 结尾的字符串 
  * BRE&ERE 匹配 0 个或任意多的单个字符,前置字符可以是正则表达式
  + ERE 匹配前面正则表达式的 1 个或多个实例
  ? ERE 匹配前面正则表达式的 0 个或 1 个实例
  [...] BRE&ERE

方括号表达式,匹配方括号内的任一字符,常配合 - 符使用,表示匹配一个连续的范围。 ^ 字符

作为方括号内的第一个字符表示匹配不在方括号内的任意字符

  - BRE&ERE 连字符,在方括号表达式中使用,表示连续字符的范围(范围会因 locale 而有所不同,因此不具可移植性)
  {n,m} ERE 区间表达式,表示匹配在它前面的字符 n 到 m次。其中,n 与 m 的值必须介于 0-RE_DUM
_MAX(含)之间,后者最小值为255
  {n} ERE 表示匹配在这之前的字符 n 次
  \{n,m\}   BRE 功能同 {n,m}
  \{n\}  BRE 功能同{n}
  \ BRE&ERE 转义符
  () ERE 匹配位于方括号括起来的正则表达式群

  \( \) BRE

将\( 与 )\ 之间的模式保存在特殊的“保留空间”中,最多可以存储9个,可以通过后续的转义序列 \n 来匹配保留空间中的模式

  \n BRE 与 \(  \)  结合起来使用,\1匹配第一个子模式、 \2匹配第二个,最多到 \9 
  | ERE 匹配位于 | 符号前或后的正则表达式

  接下来,笔者将使用 grep 命令对 /etc/passwd 文件进行查找匹配操作:

1)匹配一般字符:

[tongye@localhost ~]$ grep root /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin

2)使用点字符 " . " 匹配任意字符:

[tongye@localhost ~]$ grep r..t /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin
ftp:x:::FTP User:/var/ftp:/sbin/nologin

3)使用星号字符 " * "  或问号字符 " ? "匹配0个或多个字符:

[tongye@localhost ~]$ grep roo* /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x::::/var/lib/chrony:/sbin/nologin

  grep roo* /etc/passwd 命令将在 /etc/passwd 中匹配 ro ,后面可以接 0 个或多个 o。在 ERE 风格下,使用的是 ? 符号来达到和 * 号一样的效果:

[tongye@localhost ~]$ grep -E roo? /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x::::/var/lib/chrony:/sbin/nologin

4)使用加字符 " + " 匹配1个或多个字符:

[tongye@localhost ~]$ grep -E roo+ /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin [tongye@localhost ~]$ grep -E ro+ /etc/passwd
root:x:::root:/root:/bin/bash
operator:x:::operator:/root:/sbin/nologin
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x::::/var/lib/chrony:/sbin/nologin

  使用 + 字符可以匹配在其前面的 1 个或多个字符,与 * 字符有些许的差别,另外, + 字符实在 ERE 风格下使用的,故需要使用 grep 命令的 -E 选项

5)使用 ^ 匹配行首,$匹配行尾:

[tongye@localhost ~]$ grep ^t /etc/passwd
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
tongye:x:::tongye:/home/tongye:/bin/bash [tongye@localhost ~]$ grep ^t.*h$ /etc/passwd
tongye:x:::tongye:/home/tongye:/bin/bash

  .* 结合在一起表示匹配零个或多个任意字符,与 ^ 和 $ 结合起来使用的话就可以匹配一个指定开头和结尾的字符串了

6)使用方括号表达式匹配括号内的任一字符:

[tongye@localhost ~]$ grep [Nn]et /etc/passwd
systemd-network:x:::systemd Network Management:/:/sbin/nologin

  结合 - 字符使用,可以表示匹配一个范围内的任一字符,如 [0-9] 表示匹配 0-9 中的任意一个数字、[a-z] 表示匹配一个小写字母、[A-Z] 表示匹配一个大写字母:

[tongye@localhost ~]$ grep [a-z]c /etc/passwd
sync:x:::sync:/sbin:/bin/sync
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
abrt:x::::/etc/abrt:/sbin/nologin

  结合 ^ 字符使用,表示取反

[tongye@localhost ~]$ grep [^a-z]c /etc/passwd
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x::::/var/lib/chrony:/sbin/nologin

  这里表示匹配一个非小写字母的字符后接一个字符 c 的字符串。注意,^ 放在方括号里面表示反向含义,放在方括号外面则表示的是匹配行首。

7)使用 {n.m} 区间表达式来匹配指定的次数:

  这个表达式可以用来匹配指定的次数,其中 {n,m} 表示匹配在其前面的字符 n 到 m次,{n,} 表示至少匹配 n 次,{,m} 表示最多匹配 m 次,而 {n} 则是精准匹配 n 次。在 BRE 中,使用的是 \{n,m\} 的形式来实现相同的功能。n 与 m 的值必须介于 0 至 RE_DUP_MAX(包含这个值)之间,后者的最小值为255

[tongye@localhost ~]$ grep '\{3\}' /etc/passwd
tongye:x:1000:1000:tongye:/home/tongye:/bin/bash [tongye@localhost ~]$ grep -E {} /etc/passwd
tongye:x:1000:1000:tongye:/home/tongye:/bin/bash

8)使用 \(  \) 保存已匹配的字符,并通过 \n 来引用已保存的匹配字符串

  使用 \(  \) 会先匹配括号中的字符串,然后将匹配到的字符串保存在由正则表达式解析器预定义好的叫做寄存器的变量中,其编号从1到9,也就是说最多可以保存9组字符串,使用 \n 可以取出所保存的字符串,其中 n 为1到9,分别对应9个寄存器的值。

[tongye@localhost ~]$ grep '\(operator\).*\1' /etc/passwd
operator:x:::operator:/root:/sbin/nologin

  关于这个表达式还有一个有意思的用法:

[tongye@localhost ~]$ grep '^\(.\).*\1$' /etc/passwd
nobody:x:::Nobody:/:/sbin/nologin

  如上,正则表达式 ^\(.\).*\1$ 将匹配一个行首字符和行尾字符相同的字符串。

2.2 POSIX 方括号表达式

  为了配合非英语的环境,POSIX 标准强化其字符集范围的能力 (如 [a-z]),以匹配非英文字母字符。POSIX 使用方括号表达式 [...] 来表示一个范围值,在方括号表达式里,除了字面上的字符外(a、b、c等),另有额外的组成部分,包括:

1)字符集:以 [: ... :] 将关键字组合括起来的 POSIX 字符集,关键字描述各种不同的字符集;

2)排序符号:排序符号将多个字符序列视为一个单位(如,locale 中将 ch 这两个字符视为一个单位),它使用 [. 与 .] 将字符组合括起来,在系统所使用的特定 locale 上各有其定义;

3)等价字符集:等价字符集列出的是应视为等值的一组字符,它由取自于 locale 的名字元素组成,以 [= 与 =] 括住。

  下表是 POSIX 字符集列表:

类别 匹配字符
[:alnum:] 数字字符
[:alpha:] 字母字符
[:blank:] 空格与定位符
[:cntrl:] 控制字符
[:digit:] 数字字符
[:graph:] 非空格字符
[:lower:] 小写字母字符
[:upper:] 大写字母字符
[:space:] 空白符
[:print:] 可显示的字符
[:punct:] 标点符号字符
[:xdigit:] 十六进制数字

  需要注意的是,上述字符集也是要放到方括号表达式中去的,因此一般会出现类似 [[:alpha:]] 的表达式。

  举个例子:

[tongye@localhost ~]$ grep [[:upper:]] /etc/passwd
ftp:x:::FTP User:/var/ftp:/sbin/nologin
nobody:x:::Nobody:/:/sbin/nologin
systemd-network:x:::systemd Network Management:/:/sbin/nologin
dbus:x:::System message bus:/:/sbin/nologin
polkitd:x:::User for polkitd:/:/sbin/nologin
tss:x:::Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

  该正则表达式匹配所有的大写字母。

参考资料:

《Linux程序设计 第四版》

《Shell 脚本学习指南》

《UNIX/Linux/OS X 中的 Shell 编程 第四版》

shell基础 -- 基本正则表达式的更多相关文章

  1. Linux正则表达式、shell基础、文件查找及打包压缩

    Linux正则表达式.shell基础.文件查找及打包压缩 一.正则表达式 Linux正则表达式分为2类: 1.基本正则表达式(BRE) 2.扩展正则表达式(ERE) 两者的区别: 1.使用扩展正则表达 ...

  2. 『忘了再学』Shell基础 — 24、Shell正则表达式的使用

    目录 1.正则表达式说明 2.基础正则表达式 3.练习 (1)准备工作 (2)*练习 (3).练习 (4)^和$练习 (5)[]练习 (6)[^]练习 (7)\{n\}练习 (8)\{n,\}练习 ( ...

  3. 任督二脉之Shell中的正则表达式

    VBird说学习Linux,掌握了Shell和正则就相当于打通了任督二脉,此后能力的成长才会突飞猛进. Shell的基础学习之前已经总结了一篇博客:http://www.cnblogs.com/jyz ...

  4. Linux实战教学笔记17:精简shell基础

    第十七节 精简shell基础 标签(空格分隔): Linux实战教学笔记 1,前言 1.1 为什么学习shell编程 Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, ...

  5. Linux学习——shell编程之正则表达式和字符处理命令

    shell编程之正则表达式 一 正则表达式 1 什么是正则表达式 正则表达式用于描述字符排列和匹配模式的一种语法规则.它主要用于字符串的模式分隔.匹配.查找及替换操作. 2 shell编程之正则表达式 ...

  6. Linux Shell 基础知识(一)

    1. 本文知识结构 2. shell 基础知识 2.1 shell 简单介绍 ​ GNU bash shell 能提供对 Linux 系统的交互式访问,一般来说,使用快捷键 Ctrl + Alt + ...

  7. Shell基础学习小结

    0 shell基础概念 Shell是解释性语言,使用脚本编程语言的好处是,它们多半运行在比编译型语言还高的层级,能够轻易处理文件与目录之类的对象:缺点是它们的效率通常不如编译型语言.Shell命令有本 ...

  8. Shell基础-环境变量配置文件

    Shell基础-环境变量配置文件 source 配置文件 或者 . 配置文件: 把环境变量写入配置文件后,需要用户重新登陆才能生效,而是用source命令,则能直接生效 主要的配置文件: /etc/p ...

  9. shell基础二十篇 一些笔记

    shell基础二十篇 转自 http://bbs.chinaunix.net/thread-452942-1-1.html 研讨:Bash 内建命令 read (read命令更具体的说明见博客收藏的一 ...

随机推荐

  1. FreeRTOS+ WolfSSL + Lwip Demo

    FreeRTOS+ WolfSSL Demo下载 LWIP 源码下载  2018年2月5日09:39:08 WolfSSL is about 10 times smaller than yaSSL, ...

  2. 容易忽略的expect脚本问题,暗藏的僵尸进程,wait命令不要漏掉

    问题描述 前几天有个小需求,用到expect脚本去循环的发送一些数据,主要问题代码如下: #! /usr/bin/expect while {true} { set timeout 60 spawn ...

  3. 身份认证系统(二)多WEB应用的单点登录

    随着互联网的发展,web应用的复杂度也一直在提升,慢慢的单一的web应用已经不能满足复杂的业务需求.例如百度的搜索.新闻.百科.贴吧,其实本质上都是不同的网站.当用户使用这些平台的时候,我们当然不希望 ...

  4. 网页静态化解决方案-Freemarker

    1.1    技术简介与使用 1.1.1     简介 为什么使用: 1.  减轻数据库的访问压力,静态化比较适合大规模且相对变化不太频繁的数据: 2.  有利于SEO(搜索引擎优化); 纯的HTML ...

  5. No space left on device 解决 Cydia 安装应用错误

    在 Cydia 上搜索应用进行安装,提示错误:failed to write (No space left on device),从字面上的意思看是磁盘空间不够,导致写入错误,但是到 “关于” 里看到 ...

  6. 常见的移动端H5页面开发遇到的坑和解决办法

    转过来,平时看看.虽然还有很多问题至今无解.比如:华为麒麟950的P8和meta打开我们的应用首页经常偶发白屏.!! 1.安卓浏览器看背景图片,有些设备会模糊. 用同等比例的图片在PC机上很清楚,但是 ...

  7. 课时9.HTML发展史(了解)

    这个图片里的时间不用都记住,只需要记住一些特殊的,1993年,1995年(在W3C接手以后,才有了真正意义上的标准),1999年这几个时间 WHATWG的目的是推广HTML的标准,HTML5是浏览器厂 ...

  8. Java ArrayList 源代码分析

    Java ArrayList 之前曾经参考 数据结构与算法这本书写过ArrayList的demo,本来以为实现起来都差不多,今天抽空看了下jdk中的ArrayList的实现,差距还是很大啊 首先看一下 ...

  9. 17个C语言可以做的小案例项目

    C语言是我们大多数人的编程入门语言,对其也再熟悉不过了,不过很多初学者在学习的过程中难免会出现迷茫,比如:不知道C语言可以开发哪些项目,可以应用在哪些实际的开发中……,这些迷茫也导致了我们在学习的过程 ...

  10. Go类型特性-学习笔记

    1.组合 Go语言使用组合来完成类型的设计,设计某一类型时想要拥有其他类型的功能只需要将其他类型嵌入该类型即可. 2.接口 与其他语言不同的是,编译器会自动判断该类型是否符合某正在使用的接口,甚至不需 ...