在 sed 的基本用法里面介绍了替换命令 s,例如 将 " sed command replacement test" 中的 test 替换成 trial
echo " sed command replacement test " | sed 's/test/trial/
上面这种将一个 固定 字符串 替换 成另外一个字符串 相对比较简单,下面将介绍两种更有趣的替换。
- 单模式替换,可以 使用 & 来 存储 被匹配部分的值以供后面复用,& 相当于一个变量 。
例如,有一个通讯录 contact.txt:
zhangyu singer M 720527430 yongxinliangku
liangchaowei actor M 255376932 wujiandao
zhouhuiming singer F 248420369 zuiai
zhouxingchi director M 325851914 kongfu
需求是:将第四列的9位数qq号修改成qq 邮箱 即 720527430 换成 720527430@qq.com
实现代码:
# [0-9] 为正则表达 数字集
# [0-9]{9} 为正则表达式,表示 9 个数字,{n} 表示前面的字符重复 n 次
# & 为 sed 里面的 模式表达式,表示被匹配的内容
# {} 与 . 这两个字符 需要使用 \ 进行转义
# &@qq\.com 就是 在 匹配的 内容后面加上 @qq.com
sed 's/[0-9]\{9\}/&@qq\.com/' contact.txt
命令运行结果:
- 子模式替换,使用 () 符号 将 匹配内容 划分成 若干部分,然后再 使用 \n 来 引用 相应的 第 n 部分 值。例如, 在 (720527430)@(qq.com) 就包含了 (720527430) 和 (qq.com) 子部分,\1 引用 720527430 , \2 引用 qq.com
echo "zhangyu singer M 720527430@qq.com yongxinliangku"
# 结果 zhangyu singer M 720527430@qq.com yongxinliangku
echo "zhangyu singer M 720527430@qq.com yongxinliangku" | sed 's/\(720527430\)@\(qq\.com\)/account/'
# () 和 . 这两个符号 需要使用 \ 转义, 这个替换将 使用 account 替换 720527430@qq.com , 运行结果是: zhangyu singer M account yongxinliangku
echo "zhangyu singer M 720527430@qq.com yongxinliangku" | sed 's/\(720527430\)@\(qq\.com\)/\1account/'
# \1 引用 (720527430)@(qq.com) 中 的 第一部分, 即 \1=720527430 , 所以 \1account 就是 720527430account, 运行结果是:zhangyu singer M 720527430account yongxinliangku
echo "zhangyu singer M 720527430@qq.com yongxinliangku" | sed 's/\(720527430\)@\(qq\.com\)/\2account/'
# \2 引用 (720527430)@(qq.com) 中 的 第二部分, 即 \2=qq.com , 所以 \2account 就是 qq.comaccount, 运行结果是: zhangyu singer M qq.comaccount yongxinliangku
实践部分
有一个雇员 数据库 emp.dat ,emp.dat 有15条记录,每条记录包含7个字段: First name, Last name, Phone number, Email address, Gender, Department, Salary。 由于工作人员操作不当,导致记录“追尾”,即后一条记录的 Fist name 咬住了 前一条记录的 Salary 。原本15条记录变成了1条记录。请你将 emp.dat 里面的 Salary 与 First name 两个字段用 换行符分开,恢复成 15条记录。
# 原始数据
Jack Singh 9857532312 jack@gmail.com M hr 2000Jane Kaur 9837432312 jane@gmail.com F hr 1800Eva Chabra 8827232115 eva@gmail.com F lgs 2100Amit Sharma 9911887766 amit@yahoo.com M lgs 2350Julie Kapur 8826234556 julie@yahoo.com F Ops 2500Ana Khanna 9856422312 anak@hotmail.co m F Ops 2700Hari Singh 8827255666 hari@yahoo.com M Ops 2350Victor Sharma 8826567898 vics@hot mail.com M Ops 2500John Kapur 9911556789 john@gmail.com M hr 2200Billy Chabra 9911664321 b ily@yahoo.com M lgs 1900Sam khanna 8856345512 sam@hotmail.com F lgs 2300Ginny Singh 985712 3466 ginny@yahoo.com F hr 2250Emily Kaur 8826175812 emily@gmail.com F Ops 2100Amy Sharma 9857536898 amys@hotmail.com F Ops 2500Vina Singh 8811776612 vina@yahoo.com F lgs 2300
# 需求转换成代码 即 在 2000Jane 的 中间 加 一个 \n 符, Salary 为 4 位数字,匹配正则 [0-9]{4}, First name 为长度大于等于3的字母串,匹配正则 [a-zA-Z]{3,} 。 使用子模式替换,\1 替换 Salary, \2 替换 First name. () 与 {} 需要使用 \ 转义, 另外 全部的 Salary+First name 都要替换,所以 需要在命令后面加上标记 g 表示替换全部
sed 's/\([0-9]\{4\}\)\([a-zA-Z]\{3,\}\)/\1\n\2/g' emp.dat
# 运行结果
Jack Singh 9857532312 jack@gmail.com M hr 2000
Jane Kaur 9837432312 jane@gmail.com F hr 1800
Eva Chabra 8827232115 eva@gmail.com F lgs 2100
Amit Sharma 9911887766 amit@yahoo.com M lgs 2350
Julie Kapur 8826234556 julie@yahoo.com F Ops 2500
Ana Khanna 9856422312 anak@hotmail.com F Ops 2700
Hari Singh 8827255666 hari@yahoo.com M Ops 2350
Victor Sharma 8826567898 vics@hotmail.com M Ops 2500
John Kapur 9911556789 john@gmail.com M hr 2200
Billy Chabra 9911664321 bily@yahoo.com M lgs 1900
Sam khanna 8856345512 sam@hotmail.com F lgs 2300
Ginny Singh 9857123466 ginny@yahoo.com F hr 2250
Emily Kaur 8826175812 emily@gmail.com F Ops 2100
Amy Sharma 9857536898 amys@hotmail.com F Ops 2500
Vina Singh 8811776612 vina@yahoo.com F lgs 2300
#employinf原始数据
Jack 9857532312 jack@gmail.com hr 2000 5Jane 9837432312 jane@gmail.com hr 1800 5Eva 8827232115 eva@gmail.com lgs 2100 6amit 9911887766 amit@yahoo.com lgs 2350 6Julie 8826234556 julie@yahoo.com hr 2500 5
需求:原文本中,前一个员工的部门编号跟后一个同事的姓名咬到一个块了,应该每个员工的信息单独为一条记录。请将文本中’5Jane’, ‘5Eva’, ‘6amit’, ‘6Julie’ 分开成数字+换行+字母的形式
sed 's/\([[:digit:]]\)\([[:alpha:]]\)/\1\n\2/g' employinf
总结
单模式替换使用 & 来引用 匹配内容,子模式 使用 \1, \2, \3 …等来引用相应部分的内容,在正则表达式中使用 () 切分 子匹配模式,注意 {}, () 等特殊字符需要 使用 \ 转义