Linux操作系统基础解析之(五)——grep命令家族及正则表达式初识

grep号称文本处理三剑客之一,虽然说是三剑客中功能最少也是最简单的,但仍然不能小觑。
  grep的全称为:Global search REgular expression and Print out the line,即:全面查找正则表达式并将匹配的行显示出来。

那么这里面出现了一个新的概念:正则表达式。那么什么是正则表达式呢?

正则表达式,又称正规表示法、常规表示法英语:(Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
  给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
    1.给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”);
    2.可以通过正则表达式,从字符串中获取我们想要的特定部分。
  正则表达式的特点是:
    1.灵活性、逻辑性和功能性都非常的强;
    2.可以迅速地用极简单的方式达到字符串的复杂控制。
    3.对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎——PCRE;此外,还有java语言自带的。

主流的正则引擎又为3类:一、DFA,二、传统型NFA,三、POSIX NFA。
  DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA引擎还可以确保匹配最长的可能的字符串。但是,因为DFA引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。
  传统的NFA引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的NFA回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的NFA接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。
  POSIX NFA引擎与传统的NFA引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA引擎的速度慢于传统的NFA引擎;并且在使用POSIX NFA时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。

使用DFA引擎的程序主要有:awk, egrep, flex, lex, MySQL, Procmail等;
  使用传统型NFA引擎的程序主要有:GNU Emacs, Java, ergp, less, more, .NET语言, PCRE library, Perl, PHP, Python, Ruby, sed, vi, vim;
  使用POSIX NFA引擎的程序主要有:mawk, Mortice Kern Systems’ utilities, GNU Emacs(使用时可以明确指定);
  也有使用DFA/NFA混合的引擎:GNU awk, GNU grep/egrep, Tcl。

有了上述的一点知识,接下来继续跟大家一起来讨论grep就简单些了。为了能够满足不同用户的不同需求,grep家族中已经有了三个成员,即:grep、egrep、fgrep。其中grep是最基本的一个功能实现,如果想要更加简单的使用扩展的正则表达式,使用egrep就可以了;如果想要快速实现查找而不需要使用正则表达式的匹配的话,就要选择fgrep了。
  不管使用哪个命令,我们的目的都是唯一的:正确的从指定文件中查找得到我们感兴趣的那些行。

下面介绍以下grep命令的使用方法:
grep:外部命令
  功能:从源数据中显示出被模式匹配到的行。而且,grep默认工作在贪婪模式下,也就是说,每次grep进行模式匹配都是按照尽可能多的去完成匹配的标准进行的。
  格式:
    grep [OPTIONS] PATTERN [FILE...]
    grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
  常用选项:
    -A NUM, --after-context=NUM:被模式匹配到的行以及其后#行,如果后面没有,则不显示;不能和-o选项一同使用
    -B NUM, --before-context=NUM: 被模式匹配到的行以及其前#行,如果前面没有,则不显示;不能和-o选项一同使用
    -C NUM, -NUM, --context=NUM:被模式匹配到的行以及其前后各#行,如果前面或后面没有,则不显示;不能和-o选项一同使用
    --color=auto: 对匹配到的文本着色显示;
    -e PATTERN, --regexp=PATTERN:实现以逻辑或的关系完成多个模式的匹配,每个-e选项只能带一个模式作为参数
    -E, --extended-regexp:扩展正则表达式开关,能够让grep使用正则表达式
    -i, --ignore-case: 忽略字符大小写
    -n, --line-number:显示匹配的行在原文件中的行号
    -o, --only-matching: 仅显示匹配到的字符串;
    -q, --quiet, --silent: 静默模式,不输出任何信息;
    -v, --invert-match: 显示那些没有被模式匹配到的行;
    -w, --word-regexp:整行匹配整个单词
  退出状态:
    如果成功查找到被选中的行,状态返回值为0;否则就是1
    如果发生了错误,而且没有加-q、--quiet或--silent选项,则状态返回值为2
    
  PATTERN也可称为模式,可以有很多种构成方式:
    1.普通的字符或字符串
    2.正则表达式(元字符)

例如:
    [[email protected] ~]# grep ‘root‘ /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    此例中用于给grep提供匹配条件的PATTERN即为字符串。这样的PATTERN在匹配的时候非常机械,不灵活,所以作用并不明显。

下面针对于常用的基本正则表达式的元字符进行了一个简单的归类,希望对大家能有所帮助:

  1.通配符:
      .(点) :通用匹配任意单个字符
      []:通用匹配任意指定范围内的单个字符
      ^ :用在中括号中,对中括号中通配的字符取反,即表示"不包括"的意思.
      除此之外,GLOB所提供的通配字符集也是可以在正则表达式中被使用的。下面也列出了常用的几种:
      [:digit:]:表示所有的十进制数字,相当于0-9
      [:upper:]:表示所有的大写英文字母,相当于A,B,C,D,...,X,Y,Z
      [:lower:]:表示所有的小写英文字母,相当于a,b,c,d,...,x,y,z
      [:alpha:]:表示所有的英文字母,包括大写和小写,即上两个字符集合的并集。
      [:alnum:]:表示所有的英文字母,包括大写和小写字母,还包括所有的十进制数字,前三个字符集合的并集
      [:space:]:表示所有的空白字符。
      [:punct:]:表示所有的特殊符号,包括,./!?\;‘"-=+_等

[^[:punct:]]:表示任意一个所有的非特殊符号的字符。

2.前面字符出现次数:
      *:其前面的字符可以出现0次或任意次,相当于:\{0,\}
      \?:其前面的字符可以出现0次或1次,相当于:\{0,1\}
      \+:其前面的字符至少出现1次,相当于:\{1,\}
      \{\}:其前面的字符可以出现任意指定的次数
        \{m\}:其前面的字符必须出现m次
        \{0,m\}:其前面的字符可以出现0次或最多m次
        \{m,\}:其前面的字符至少出现m次
        \{m,n\}:其前面的字符至少出现m次,最多出现n次

3.锚定字符:
      ^ :行首锚定字符
      $ :行尾锚定字符
      \<:词首锚定字符
      \>:词尾锚定字符

4.分组字符:
      \(\):将括于括号中的字符分为一组
      在正在表达式处理引擎中,如果一旦发现小括号,就按照括号出现的顺序,将对应位置的括号里面的内容记录到某个特定的变量中,而调用这些变量中存储数值的方法,叫做"后向引用",也就是使用\1, \2, \3, ...等

5.选择字符:
    \|:或者,表示或者符号左右的整体是可选的内容
      如:b\|root,表示b或者root两种情况
          \(b\|r\)oot则表示boot或root两种情况,后者是使用\(\)分组的结果。

注意:使用正则表达式元字符的时候,一定要注意以下几点:
      1.正则表达式是由正则表达式的元字符构成的,在构成正则表达式的时候,各个元字符之间一般没有空白字符。
      2.最好是在引号中使用正则表达式的元字符,否则可能会被shell解释而不是被正则表达式引擎处理了。
      3.在书写引号的时候,单引号和双引号都可以,但是要考虑到$字符的使用,一旦有$用来表示行尾,则必须使用单引号,否则将会被shell解释为变量引导符,从而企图将其后面的字符串理解成变量名,从而取到控制,而干扰了我们的使用
      4.如果想要使用字符本身,比如".",则需要在这个元字符前面加"\"即可,如"."表示任意单个字符,而‘\.‘则仅仅只是表示.这个字符本身,有的时候,我们可能要匹配域名或者IP地址,则必须用这个方法才可以。
      5.在我们书写正则表达式的时候,应该尽可能周密的思考问题,尽可能把各种情况都考虑进来,从而才能写出最符合要求的正则表达式。  

扩展的正则表达式的元字符:
    包括了所有的基本正则表达式的元字符,同时有了新的规定:
      \? --> ?
      \{\} --> {}
      \(\) --> ()
      \+ --> +
      \| --> |
      词首锚定和词尾锚定中的"\"依然被保留。

下面我们来做几个例子,以方便大家的理解。

1.取出/etc/sysconfig/network-scripts/ifcfg-eno16777736这个文件的基名

[[email protected] ~]# echo /etc/sysconfig/network-scripts/ifcfg-eth0 | grep -o "[^\/]\+\/\?$" | tr -d ‘/‘
ifcfg-eth0


2.找出/etc/rc.d/init.d/functions文件中某单词(包括下划线)后面跟一个小括号的行

[[email protected] ~]# grep -o ".*_*.*()" /etc/init.d/functions
systemctl_redirect ()
checkpid()
__pids_var_run()
__pids_pidof()
daemon()
killproc()
pidfileofproc()
pidofproc()
status()
echo_success()
echo_failure()
echo_passed()
echo_warning()
update_boot_stage()
success()
failure()
passed()
warning()
action()
strstr()
is_ignored_file()
is_true()
is_false()
apply_sysctl()

3.显示/etc/passwd文件中用户名与该用户的默认shell名相同的用户账户信息

[[email protected] ~]# grep -E "(\<.+\>).*\1$" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt


4.显示利用ldd命令查看到的ls命令所使用的动态库文件的绝对路径

[[email protected] ~]# ldd /bin/ls | egrep -o "/.*lib(64)?/[^[:space:]]+"
/lib64/libselinux.so.1
/lib64/libcap.so.2
/lib64/libacl.so.1
/lib64/libc.so.6
/lib64/libpcre.so.1
/lib64/liblzma.so.5
/lib64/libdl.so.2
/lib64/ld-linux-x86-64.so.2
/lib64/libattr.so.1
/lib64/libpthread.so.0
时间: 2024-08-05 11:17:06

Linux操作系统基础解析之(五)——grep命令家族及正则表达式初识的相关文章

Linux操作系统基础解析之(四)——Linux基本命令剖析(1)

Linux操作系统自从出现以来,就备受关注.但是人们往往会有这样的一个印象:Linux比Windows难.为什么好多人都会有这样的想法呢?很简单,因为Windows是在更早的时候,甚至是大多数国人都没有认识到计算机的时候就已经被安装到X86架构的计算机上了.Microsoft公司寻求Intel公司的技术支持,并且建立合作之后,PC的市场就几乎被这两家公司垄断了.所以,很多人刚刚开始接触并逐渐学会使用计算机,Intel的X86架构的主机,而且这个主机上一般安装的都是Windows操作系统.因此,大

Linux操作系统基础解析之(六)——文件系统层次结构标准(FHS)

一切皆文件是Linux的最基本的最朴素的哲学思想之一.意思就是说:凡是在Linux操作系统中能够被访问和使用的资源,都会以文件的形式提供给用户,即便是硬件设备.进程互操作.网络访问等这些看似与文件无关的内容,也可以虚拟抽象成文件,这就是Linux操作系统.也就是说,在一个完整意义的Linux操作系统中,存在的大量的.数以万计的文件.这些文件有的是硬件设备,有的是管道,有的是套接字,目录文件,符号链接文件,设备锁文件,进程锁文件,被编译好的二进制文件(可执行应用程序.库文件.内核文件).压缩包文件

Linux操作系统基础解析之(三)——基本操作及获得帮助

我们传统意义上理解的操作系统实际上是指:包括了操作系统的kernel,以及在其上构建了大量的功能各异的应用程序的集合体.所以狭义上来讲,操作系统就是指kernel.kernel将底层的硬件的复杂逻辑屏蔽掉,将硬件虚拟化为更加容易使用和访问的资源,向上层的应用程序提供调用接口,从而可以保证应用程序能够正常运行,能够访问和使用硬件资源.在这些应用程序中,有一类应用程序是非常特殊的,它是操作者使用计算机的入口,是操作者完成交互式登录以及交互式作业的基础,这种应用程序我们称之为接口程序,或者叫用户访问界

Linux操作系统基础解析之(七)——Bash(Shell)基础知识(1)

在日常交际英语中,Shell可以翻译成壳,大多指能够对内部核心起到保护作用的一种装置或结构.在计算机科学中,shell其实是指:为操作者提供的.能够通过系统调用或库调用使用整个计算机资源的访问接口. 它既是一种命令解析器又是一种程序设计语言.作为命令解析器,它可以解释和执行用户输入的命令,也可以自动地解释和执行预先编写好并保存在某个文本文件中的一系列的命令:作为程序设计语言,shell特别定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和条件分支,让我们可以像使用高级语言

Linux操作系统基础解析之(七)——bash基础知识和基本使用技巧(1)

在日常交际英语中,Shell可以翻译成壳,大多指能够对内部核心起到保护作用的一种装置或结构.在计算机科学中,shell其实是指:为操作者提供的.能够通过系统调用或库调用使用整个计算机资源的访问接口.    它既是一种命令解析器又是一种程序设计语言.作为命令解析器,它可以解释和执行用户输入的命令,也可以自动地解释和执行预先编写好并保存在某个文本文件中的一系列的命令:作为程序设计语言,shell特别定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和条件分支,让我们可以像使用高

linux操作系统基础篇(五)

Linux网络以及rpm安装yum源的配置 1.Linux网络 1. 使用ifconfig命令来维护网络(详见linux系统管理P422)1) fconfig命令的功能:显示所有正在启动的网卡的详细信息或设定系统中网卡的IP地址.2) 用ifconfig命令设定网卡的IP地址:例如:修改eth0网卡的IP地址为172.18.48.56和子网掩码255.255.255.128的命令:ifconfig eth0 172.18.48.56 netmask 255.255.255.1282. 使用ifu

Linux操作系统基础解析之(七)——Bash(Shell)基础知识(5)

十一.函数  shell函数就是按照上面SHELL GRAMMAR的描述定义的保存着一系列等待稍后执行的命令.当shell函数名被当做一个简单命令名使用时,被这个函数名关联的一系列命令都被执行.函数在当前shell的上下文环境中被执行:不会创建新的进程来解释它们(这与shell脚本的执行形成了对比).当执行函数时,函数的参数成为执行过程中的位置参数.特殊参数#被更新以反映这个变化.特殊参数0不会改变.函数执行时,FUNCNAME变量的第一个元素被设置为函数的名称.  shell执行环境的所有其他

Linux操作系统基础解析之(七)——Bash(Shell)基础知识(3)

五.注释 在非交互shell中或交互式shell中,内置命令shopt的选项interactive_comments被开启.以"#"开始的词使得这个词所在这一行上所有其他的剩余字符都被忽略(或称注释).交互式shell不用开启interactive_comments选项也不支持注释.interactive_comments选项在交互式shell中是默认启用的.注释是编写程序时,写程序的人给一个语句.程序段.函数等的解释或提示,能提高程序代码的可读性,以便于以后的参考.修改.后来,在应用

Linux操作系统基础知识(五)

ifconfig 命令查看网络信息eth0 eth1em1 em2p2p2 p2p3 systemctl status network 查看网络状态systemctl start networksystemctl stop networksystemctl restart network 网络管理网络管理设置ipsetupservice network restart网卡配置文件/etc/sysconfig/network-scripts/ifcfg-eth0 ifconfig eth0ifco