本文继续学习shell脚本编程,文本查找与文本替换
1、查找文本
以grep程序查找文本(匹配文本)很方便
有三种程序可以用来查找整个文本文件:
grep
最早的文本匹配程序,使用POSIX定义的基本正则表达式
egrep
扩展式grep,功能更加强大,但是代价是会耗费更多的运算资源
fgrep
快速grep,这个版本匹配固定的字符串而非正则表达式,使用优化的算法
这三种grep最后合并在2001POSIX标准的grep命令
grep最简单的用法就是使用固定字符串:
wu@ubuntu:~$ who
wu :0 2016-11-16 06:03 (:0)
wu pts/12 2016-11-16 06:04 (:0)
wu@ubuntu:~$ who | grep -F w
wu :0 2016-11-16 06:03 (:0)
wu pts/12 2016-11-16 06:04 (:0)
-F选项用以查找固定字符串w
本文地址:http://wuyudong.com/2016/11/18/3048.html,转载请注明出处。
2、正则表达式
正则表达式有两个基本部分组成:一般字符和特殊字符
字符 | BRE/ERE | 模式含义 |
\ | 两者都可 | 用以关闭后续字符的特殊意义 |
. | 两者都可 | 匹配单个字符,但NUL除外 |
* | 两者都可 | 匹配在它之前的任意数量的单个字符 |
^ | 两者都可 | 匹配紧接着的正则表达式,在行或字符串的起始处 |
$ | 两者都可 | 匹配前面的正则表达式,在字符串或行结尾出处 |
[…] | 两者都可 | 匹配方括号内任一字符,连字符(-)表示连接字符的范围 |
匹配单个字符
- 一般字符就是它自身
- 转义字符\
- .字符即任意字符
- 使用方括号[],里面的^放在字首表示取反
后向引用
首先,将子表达式包含在\ ( \ )中。最多包含9个子表达式
然后,使用\digit,其中digit可以是1-9,表示与先前第digit个子表达式匹配
例如:
模式 | 匹配成功 |
\ (ab\ )\ (cd\ )[def]*\2\1 | abcdcdab、abcdeeecdab、abcdddeeffcdab、…… |
\ (why\ ).*\1 | 一行里重现两个why |
后向引用在寻找重复字以及匹配引号时特别好用:
\ ([” ‘]\ ).*\1 匹配单引号或双引号括起来的字
单个表达式匹配多字符
使用.或者*进行匹配,但是*修饰符不能表明匹配次数,区间表达式可以解决这类问题,区间表达式接在单个字符正则表达式后面,控制该字符连续重复几次即为匹配成功。
区间表达式将一个或两个数字放在\{与\}之间,有3种变化,如下:
\ {n\ } 前置正则表达式所得结果重现n次
\ {n,\ } 前置正则表达式所得结果重现至少n次
\ {n,m\ } 前置正则表达式所得结果重现n至m次
例如:
a\ {5\ } 表示重现5个a
q\ {10,42\ } 表示重现10到42个q
至于n与m的值必须介于0~RE_DUP_MAX之间,可以通过$getconf命令查看:
wu@ubuntu:~$ getconf RE_DUP_MAX
32767
文本匹配锚点
两个meta字符(^与$)叫做锚点,针对要被匹配字符串的开始或结尾处进行匹配
^与$可以同时使用,将括起来的正则表达式匹配整个字符串
3、字段处理
一条记录指的是相关信息的单个集合,而字段指的是记录的组成部分
文本文件惯例
一行表示一条记录,使用空格或tab分隔字段,例如:
wu@ubuntu:~/bin$ cat record1.data
#name age address
zhangsan 20 guangzhou
lisi 21 beijing
wangwu 22 shenzhen
…
#起到注释的作用,也可以使用冒号来界定分隔字段,但无论使用哪种,定界符最好不要成为数据的内容
以定界符分隔字段最好的例子就是/etc/passwd
wu@ubuntu:~/bin$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
……
在这个文件里,一行表示系统里的一个用户,每个字段都以冒号隔开
使用cut选定字段
cut命令是用来剪下文本文件里的数据,文本文件可以是字段类型或是字符类型。
下面的命令显示系统上每个用户的登录名以及其全名:
wu@ubuntu:~/bin$ cut -d : -f 1,5 /etc/passwd
root:root
daemon:daemon
bin:bin
sys:sys
……
通过选择其他字段编号,还可以取出每个用户的根目录:
wu@ubuntu:~/bin$ cut -d : -f 6 /etc/passwd
/root
/usr/sbin
/bin
/dev
……
使用join连接字段
join命令可以将多个文本结合在一起,每个文件里面的记录都共用一个键值
wu@ubuntu:~/bin$ cat sales
#业务数据
#业务员 数量
张三 100
李四 200
王五 300
wu@ubuntu:~/bin$ cat quotas
#配额
#业务员 配额
张三 50
李四 30
王五 45
为了让join运作得到正确的结果,输入文件必须先完成排序,merge-sales.sh
#! /bin/sh # merge-sales.sh # # 结合配额与业务员数据 # 删除注释并排序数据文件 sed '/^#/d' quotas | sort > quotas.sorted sed '/^#/d' sales | sort > sales.sorted # 以第一个键值作结合,将结果产生至标准输出 join quotas.sorted sales.sorted # 删除缓存文件 rm quotas.sorted sales.sorted
运行结果如下:
wu@ubuntu:~/bin$ merge-sales.sh
张三 50 100
李四 30 200
王五 45 300
Comments