重点回顾
正规表示法就是处理字串的方法,他是以行为单位来进行字串的处理行为; 正规表示法透过一些特殊符号的辅助,可以让使用者轻易的达到『搜寻/删除/取代』某特定字串的处理程序; 只要工具程序支持正规表示法,那么该工具程序就可以用来作为正规表示法的字串处理之用; 正规表示法与万用字节是完全不一样的东西!万用字节 (wildcard) 代表的是 bash 操作介面的一个功能, 但正规表示法则是一种字串处理的表示方式! 使用 grep 或其他工具进行正规表示法的字串比对时,因为编码的问题会有不同的状态,因此, 你最好将 LANG 等变量配置为 C 或者是 en 等英文语系! grep 与 egrep 在正规表示法里面是很常见的两支程序,其中, egrep 支持更严谨的正规表示法的语法; 由於编码系统的不同,不同的语系 (LANG) 会造成正规表示法撷取数据的差异。因此可利用特殊符号如 [:upper:] 来替代编码范围较佳; 由於严谨度的不同,正规表示法之上还有更严谨的延伸正规表示法; 基础正规表示法的特殊字符有: *, ?, [], [-], [^], ^, $ 等! 常见的正规表示法工具有: grep , sed, vim 等等 printf 可以透过一些特殊符号来将数据进行格式化输出; awk 可以使用『栏位』为依据,进行数据的重新整理与输出; 文件的比对中,可利用 diff 及 cmp 进行比对,其中 diff 主要用在纯文字文件方面的新旧版本比对 patch 命令可以将旧版数据升级到新版 (主要亦由 diff 创建 patch 的补丁来源文件)
本章习题
( 要看答案请将鼠标移动到『答:』底下的空白处,按下左键圈选空白处即可察看 )
情境模拟题一:
透过 grep 搜寻特殊字串,并配合数据流重导向来处理大量的文件搜寻问题。
目标:正确的使用正规表示法; 前提:需要了解数据流重导向,以及透过子命令 $(command) 来处理档名的搜寻;
我们简单的以搜寻星号 (*) 来处理底下的任务:
1、利用正规表示法找出系统中含有某些特殊关键字的文件,举例来说,找出在 /etc 底下含有星号 (*) 的文件与内容:
解决的方法必须要搭配万用字节,但是星号本身就是正规表示法的字符,因此需要如此进行:
[AppleScript] ı鿴 ƴ
[root@www ~]# grep '\*' /etc/*
你必须要注意的是,在单引号内的星号是正规表示法的字符,但我们要找的是星号,因此需要加上跳脱字符 (\)。但是在 /etc/* 的那个 * 则是 bash 的万用字节! 代表的是文件的档名喔!不过由上述的这个结果中,我们仅能找到 /etc 底下第一层子目录的数据,无法找到次目录的数据, 如果想要连同完整的 /etc 次目录数据,就得要这样做:
[AppleScript] ı鿴 ƴ
[root@www ~]# grep '\*' $(find /etc -type f)
2、但如果文件数量太多呢?如同上述的案例,如果要找的是全系统 (/) 呢?你可以这样做:
[AppleScript] ı鿴 ƴ
[root@www ~]# grep '\*' $(find / -type f)
-bash: /bin/grep: Argument list too long
真要命!由於命令列的内容长度是有限制的,因此当搜寻的对象是整个系统时,上述的命令会发生错误。那该如何是好? 此时我们可以透过管线命令以及 xargs 来处理。举例来说,让 grep 每次仅能处理 10 个档名,此时你可以这样想:
先用 find 去找出文件; 用 xargs 将这些文件每次丢 10 个给 grep 来作为参数处理; grep 实际开始搜寻文件内容。
所以整个作法就会变成这样:
[AppleScript] ı鿴 ƴ
[root@www ~]# find / -type f | xargs -n 10 grep '\*'
3、从输出的结果来看,数据量实在非常庞大!那如果我只是想要知道档名而已呢?你可以透过 grep 的功能来找到如下的参数!
[AppleScript] ı鿴 ƴ
[root@www ~]# find / -type f | xargs -n 10 grep -l '\*'
情境模拟题二:
使用管线命令配合正规表示法创建新命令与新变量。我想要创建一个新的命令名为 myip , 这个命令能够将我系统的 IP 捉出来显示。而我想要有个新变量,变量名为 MYIP ,这个变量可以记录我的 IP 。
处理的方式很简单,我们可以这样试看看:
首先,我们依据本章内的 ifconfig, sed 与 awk 来取得我们的 IP ,命令为:
[AppleScript] ı鿴 ƴ
[root@www ~]# ifconfig eth0 | grep 'inet addr' | \
> sed 's/^.*inet addr://g'| cut -d ' ' -f1
再来,我们可以将此命令利用 alias 指定为 myip 喔!如下所示:
[AppleScript] ı鿴 ƴ
[root@www ~]# alias myip="ifconfig eth0 | grep 'inet addr' | \
> sed 's/^.*inet addr://g'| cut -d ' ' -f1 "
最终,我们可以透过变量配置来处理 MYIP 喔!
[AppleScript] ı鿴 ƴ
[root@www ~]# MYIP=$( myip )
如果每次登陆都要生效,可以将 alias 与 MYIP 的配置那两行,写入你的 ~/.bashrc 即可!
简答题部分:
我想要知道,在 /etc 底下,只要含有 XYZ 三个字节的任何一个字节的那一行就列出来,要怎样进行?+ 答案 (点击展开) - 答案 (点击折叠) grep [XYZ] /etc/*
将 /etc/termcap 内容取出后,(1)去除开头为 # 的行 (2)去除空白行 (3)取出开头为英文字母的那几行 (4)最终统计总行数该如何进行?+ 答案 (点击展开) - 答案 (点击折叠) grep -v '^#' /etc/termcap | grep -v '^$' | grep '^[[:alpha:]]' | wc -l
参考数据与延伸阅读
注1:关於正规表示法与 POSIX 及特殊语法的参考网址可以查询底下的来源:
维基百科的说明:http://en.wikipedia.org/wiki/Regular_expression
ZYTRAX 网站介绍:http://zytrax.com/tech/web/regex.htm
洪朝贵老师的网页:http://www.cyut.edu.tw/~ckhung/b/re/index.php
龙门少尉的窝:http://main.rtfiber.com.tw/~changyj/
PCRE 官方网站:http://perldoc.perl.org/perlre.html
注3:关於 ASCII 编码对照表可参考维基百科的介绍:
维基百科 (ASCII) 条目: http://zh.wikipedia.org/w/index.php?title=ASCII&variant=zh-tw
注4:关於 awk 的进阶文献,包括有底下几个连结:
中研院计算中心 ASPAC 计画之 awk 程序介绍:http://phi.sinica.edu.tw/aspac/reports/94/94011/
鸟哥备份:http://cn.linux.vbird.org/linux_basic/0330regularex/awk.pdf
这份文件写的非常棒!欢迎大家多多参考!
Study Area:http://www.study-area.org/linux/system/linux_shell.htm