Sed基础入门
参照:张昊著《LINUX Shell编程从入门到精通》,Richard Blum著《Linux命令行与shell脚本编程大全》
希望大家在学习前先看看正则表达式,正则表达式在Linux文本处理中会经常用到,这里不会介绍正则表达式。
【一、初识sed】
- sed是编辑器,是基于行的,按顺序对每一行执行命令。
- 命令选项:
- -e script : 在处理输入时,将script中指定的命令添加到运行的命令中
- -f file: 在处理输入时,将file中指定的命令添加到运行的命令中
- -n: 不要主动输出,等待p输出命令时才输出
- 要在命令行上执行多个命令,要用-e选项,命令之间用 ; 分隔
- 如:sed –ne ‘=; p’ /etc/passwd
- 要读取文件中的sed命令,使用-f选项
- 如上图中,s代表替换命令,找到bash并用mysh替换,找到包含gr的行打印出来,可以看到,/bin/bash已被修改为/bin/mysh
【二、sed编辑器基础】
- 删除(d)
- 对匹配的行进行删除操作
- sed ‘2d’ data 删除第2行
- sed ‘2,$d’ data 删除第2行到尾行
- 对匹配的行进行删除操作
- 替换(s)
- 使用地址
- 数字方式的行寻址
- sed ‘2d’ /etc/passwd 删除第二行
- sed ‘2,5d’ /etc/passwd 删除第2到5行
- sed ‘2,$s/gr/mygr/g’ /etc/passwd 从第2行到最后一行把所有gr换成mygr
- 正则过滤行
- sed -n ‘/gr/p’ 查找有gr的行并输出
- 组合命令
- 有时需对匹配到的行执行多条命令,用{}括起来
- sed ‘2{s/fox/elephant/; s/dog/cat/} data 对第2行执行两条替换命令
- 有时需对匹配到的行执行多条命令,用{}括起来
- 若没有地址匹配,则是对每行都进行处理
- 数字方式的行寻址
- 插入(i)
- 在指定行前增加一个新行,形式:sed ‘[address]command\”new line”’
- echo “Test Line 2” | sed ‘i\Test Line 1’
- 在指定行前增加一个新行,形式:sed ‘[address]command\”new line”’
- 附加(a)
- 修改(c)
- 和插入,附加命令相似,只是修改指定行的内容
- sed ‘$c\
- this is the changed line.’ data 将最后一行的内容改为this is the changed line.
- sed ‘$c\
- 和插入,附加命令相似,只是修改指定行的内容
- 转换(y)
- 唯一可以处理单个字符的sed编辑器命令,形式:[address]y/inchars/outchars/
- sed ‘$y/abc/ABC/’ data 把a换成A,b换成B,c换成C
- 唯一可以处理单个字符的sed编辑器命令,形式:[address]y/inchars/outchars/
- 打印
- 打印行
- sed –n ‘3p’ 打印第3行
- 打印行号
- sed ‘=’data 在行的上面插入一行表示行号
- 列出行(l)
- 打印不可见字符,如用\t代表制表符
- 打印行
- 写入(w)
- 使用w命令进行保存
- sed ‘3w data_bak’ data 将data中的第3行写入data_bak中
- 使用w命令进行保存
- 读取(r)
- 使用r命令读取文件,会在指定行后面插入文件中的所有内容,形式[address]r filename
- 不能指定范围地址,因为它要在指定一行后面插入
- 如果想用文件中的内容替换指定行,而不是添加在该行后面,只需在最后删除该行:
- sed ‘${r
- /etc/passwd
- d
- }’data 在data文件尾行插入/etc/passwd内容,并删除尾行
- sed ‘${r
- 使用r命令读取文件,会在指定行后面插入文件中的所有内容,形式[address]r filename
【三、sed进阶】
- 这里先给一个经典的例子,去除html标签,只显示其中的文本
- 这里,只需要将<>标签删除即可,如:<title>this is test page</title>
- 读者也许会用 sed ‘s/<.*>//g’ index.html 去处理, .* 会匹配任意多个字符
- 但sed采用的最长匹配,已就是说,它会找到后面的</title>中的>,所有这一行都会被删除(包括文本内容)
- 为了避免这种问题,这里匹配的时候要确保< >中间没有>,所有命令如下:
- sed ‘s/<[^>]*>//g’ index.html ,这样的话,遇到<title>中的>就会匹配结束,删除该<title>标签,同理,匹配删除</title>
- 这里,只需要将<>标签删除即可,如:<title>this is test page</title>
- 多行命令
- next命令
- 小写n: 移动数据流到下一行
- 大写N: 将下一行加入当前行处理
- sed ‘/first/{N; s/\n//g}’ data
- 多行删除命令,D只会删除多行中的第一行,删除第一行包括\n,并且回环到脚本的起始处
- 删除首行空白行,已知第2行含header单词
- sed ‘^${N;/header/D}’data 首先会查找空白行,然后加入下行,判断是否存在headder,若存在,则删除第一行
- 打印多行,P只会打印多行中的第一行
- next命令
- 保持空间
- 模式空间是一块活动缓冲区,利用保持空间来临时保存一些行
- h 将模式空间复制到保持空间
- H 将模式空间附加到保持空间
- g 将保持空间复制到模式空间
- G 将保持空间附加到模式空间
- x 交换模式空间和保持空间的内容
- sed –n ‘/first/{
- h
- p
- n
- p
- g
- p
- }’ data
- h 先将含有first行放到保持空间,p打印模式空间
- n 移动到下一行,p打印模式空间
- g 将保持空间放到模式空间,即刚才含first的行,并打印模式空间
- 模式空间是一块活动缓冲区,利用保持空间来临时保存一些行
- 排除命令
- 使用!排除命令,让原本起作用的命令不起作用
- sed –n ‘/first/!p’ data 本来是只打印含有first行;现在正好相反,含有first行的不会打印,其它行都打印
- 反转数据流文本行的顺序,先输出最后一行,最后输出第一行
- 在模式空间放置1行
- 先将模式空间的1行放到保持空间
- 在模式空间放入下一行
- 将保持空间内容附加到模式空间 (G 命令)
- 将模式空间内容放到保持空间 (h 命令)
- 注意,第1行不要进行G操作,最后一行进行打印操作
- sed –n ‘1!G; h; $p’ data
- 使用!排除命令,让原本起作用的命令不起作用
- 改变流
- 跳转(b),对命令进行跳转,执行指定命令,形式如下:[address] b [label]
- address参数决定了哪行数据触发跳转命令,若label未指定,则默认跳转到命令脚本结尾
- sed ‘{2,3b; s/dog/cat/; s/head/tail/}’ data 在2,3行触发跳转到最后,不执行替换命令
- sed –n ‘{:start; s/,//1p; /,/b start}’data 如果有,则跳到start,并替换,
- 测试(t),基于替换命令跳转到下一个标签,而不是基于地址跳转到一个标签
- sed ‘{s/first/matched/; t; s/hello/world/}’ data
- 查找first,如果匹配了选中的模式,测试命令会跳过后面替换命令,如果,第一个命令没有匹配,第二个命令就会被执行。
- 跳转(b),对命令进行跳转,执行指定命令,形式如下:[address] b [label]
- 模式替代
- and(&)符号
- echo “the cat sleeps in his hat.” | sed ‘s/.at/”&”/g’ 用&代替前面匹配的项,如cat,hat
- 替换单独的单词,使用小括号
- sed “that furry cat is pretty” | sed ‘s/furry \(.at\)/\1/’ that cat is pretty
- 用\1代替前面小括号里匹配的单词,小括号加\,说明为聚合字符,而不是普通的小括号
- and(&)符号