sed学习
在Mac OS上使用sed是BSD sed 会产生很多的不便,因此可以替换一下
1 | brew install gnu-sed |
sed(stream editor)流编辑器,用程序的方式来编辑文本。基本上使用正则模式匹配。
s替换命令
首先写一下可能会用到的正则的东西
语法 | 作用 | 例子 |
---|---|---|
^ | 一行的开始 | /^#/ 以#开头的匹配 |
$ | 一行的结尾 | /}$/ 以}结尾的匹配 |
\< | 字符串的开始 | /<adc 表示以abc为首的词 |
> | 字符串的结尾 | abc/> 表示以abc为尾的词 |
. | 任何单个字符 | |
* | 某个字符出现0到无限次 | |
[] | 字符集 |
有一段如下的文字pet.txt:
1 | This is my cat |
要把其中的my
替换为Dlala's
,就使用
1 | sed "s/my/Dlala's/g" pet.txt |
这里使用""
是为了能转义,其中,s
代表替换命令,/my/
代表匹配my,’/Dlala’s/‘代表把匹配替换成Dlala’s,/g和正则中一样,为全局模式,表示一行上替换所有的匹配。
上述的sed并没有对文件的内容进行修改,只是把处理后的内容输出出来,如果要修改原文件,就使用重定向,如下
1 | sed "s/my/Dlala's/g" pet.txt > Dlala_pet.txt |
或者也可以使用-i
参数直接修改文件的内容:
1 | sed -i "s/my/Dlala's/g" pet.txt |
这里如果使用OS X的话要这样写
1 | sed -i '' "s/my/Dlala's/g" pet.txt |
来写个实例,获取html标签内的内容
index.html如下
1 | <p> |
使用sed命令如下:
1 | sed "s/<[^>]*>//g" index.html |
输出如下:
1 | This is what I meant. Understand? |
在每一行的前面加东西:
1 | sed "s/^/#/g" pet.txt |
在每一行的后面加东西:
1 | sed "s/$/ --- /g" pet.txt |
替换第三行的制定内容
1 | sed "3s/my/your/g" pet.txt |
替换3到6行的指定内容
1 | sed "3,6s/my/your/g" pet.txt |
修改一个txt如下:
1 | This is my cat, my cat's name is betty |
只替换每一行的第一个s:
1 | sed "s/s/S/1" pet.txt |
只替换每一行的第二个s:
1 | sed "s/s/S/2" pet.txt |
只替换每一行的第三个以后的s:
1 | sed "s/s/S/3g" pet.txt |
此命令只能在Linux下执行,原因还是sed的版本问题。
使用&来当做被匹配的变量,然后在其左右加内容
1 | sed 's/my/[&]/g' pet.txt |
多个匹配
如果需要一次替换多个模式,可以使用多个匹配,每个模式之间使用;分割,下面写两个例子:
第一个例子是这样的,替换一到三行的my,并且第三行到最后一行的This
1 | sed '1,3s/my/your/g; 3,$s/This/That/g' pet.txt |
这里的''
不能用""
代替!
上述的命令等价于:
1 | sed -e'1,3s/my/your/g' -e '3,$s/This/That/g' pet.txt |
(这里就使用了sed的-e命令行参数)这里也不要使用""
因为会造成$
不起作用的情况。
圆括号匹配
圆括号括起来的正则表达式所匹配的字符串可以当成变量来使用,sed中使用的是\1,\2…
1 | sed 's/This is my \([^,]*\),.*is \(.*\)/\1:\2/g' pet.txt |
输出结果:
1 | cat:betty |
sed的命令
N命令
N命令–把下一行的内容纳入当成缓冲区做匹配。
例如,当使用N
来处理以下pet.txt文件时
1 | This is your cat |
会把原文本中的偶数行纳入奇数行进行匹配,就成了以下效果:
1 | This is my cat\n my cat's name is betty |
那么使用命令
1 | sed 'N;s/\n/,/' pet.txt |
就会出现以下效果:
1 | This is my cat, my cat's name is betty |
a命令和i命令
a : append
i : insert
这两条命令是用来添加行的。分别举个例子:
1 | sed "1 i This is Lyh" |
表示在第一行前插入一行(insert)
1 | sed "1 a This is Lyh" |
表示在第一行后插入一行(append)
还可以使用匹配来添加文本:
1 | sed "/fish/a This is Lyh" pet.txt |
d命令
删除匹配行,举三个例子
1 | sed '/fish/d' pet.txt |
p命令
p命令可以理解为是grep式的命令
1 | # 匹配fish并输出,可以看到fish的那一行被打了两遍, |
基本知识
Pattern Space: 关于参数-n,表示取消默认输出,相当于–quiet,–silent。在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。
Address:[address[,address]][!]{cmd},其中的!表示匹配成功后是否执行命令,address可以是一个数字,也可以是一个模式,可以通过逗号分隔两个address表示两个address的区间。
命令打包:cmd可以是多个,它们可以用分号分开,可以用大括号括起来作为嵌套命令
举个例子:
1 | sed '3,6 {/This/{/fish/d}}' pet.txt |
1 | sed '1,${/This/d ; s/^ *//g}' pets.txt |
- HoldSpace: 保持空间
1 | g:将hold space中的内容拷贝到pattern space中,原来pattern space里的内容清除 |
举个例子:
1 | sed -e '/test/h' -e '$G‘ example |
在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。
1 | sed -e '/test/h' -e '/check/x' example |
互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。
- 执行sed脚本:sed -f test.sed
Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。
ps: 去除空白行:sed ‘/^ *$/d’ file