Linux学习笔记(九)
sed实例讲解
上篇 博客已经讲解了sed的基本命令及其使用方法,sed有两种方式进行调用:
sed [-n] [-e] 'command(s)' files
sed [-n] -f scriptfile files
sed各个选项
替换命令:s命令
sed的替换命令语法如下:
s/pattern/replacement/
现在有一个包含3列10行的数据集chroms.txt:
$ head -n 3 chroms.txt
chrom1 3214482 3216968
chrom1 3216025 3216968
chrom1 3216022 3216024
我们要将chrom替换成chr:
$ sed 's/chrom/chr/' chroms.txt |head -n 3
chr1 3214482 3216968
chr1 3216025 3216968
chr1 3216022 3216024
不管是pattern还是replacement都是被两个斜杠/包围,叫做定界符,定界符不仅仅只有/,还有:|等 sed有部分命令会直接修改原文件,所以使用过程中最后将结果redirect到一个新的文件
-n选项和p命令一起使用表示只打印那些发生替换的行
$ cat company.txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
$ sed -n 's/u/U/p' company.txt
baidU 100 5000
sohU 100 4500
gUge 50 3000
选项-i会匹配文件中每一行的第一个匹配
$ cat company.txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
$ sed -i 's/g/G/' company.txt
$ cat company.txt
baidu 100 5000
sohu 100 4500
Google 110 5000
Guge 50 3000
全面替换标记g
使用后缀/g标记会替换每一行中的所有匹配
$ sed 's/g/G/g' company.txt
baidu 100 5000
sohu 100 4500
GooGle 110 5000
GuGe 50 3000
从第n个匹配处开始匹配标记ng
$ sed 's/g/G/2g' company.txt
baidu 100 5000
sohu 100 4500
gooGle 110 5000
guGe 50 3000
上面是从第二个匹配处开始替换,所以第一个g没有发生替换
-E选项调用扩展正则表达式
sed默认使用的时POSIX的基本正则表达式(BRE),通过选项-E我们可以使用扩展版的正则表达式(ERE),举个例子,假设我们有一个字符串:chr1:28427874-28425431,分别代表染色体(chr)、start position以及end position,我们要将这三者分离开来形成3列:
$ echo 'chr1:28427874-28425431'|sed -E 's/^(chr[^:]+):([0-9]+)-([0-9]+)/\1\t\2\t\3/'
chr1 28427874 28425431
看起来有点复杂,主要是涉及到正则表达式,拆开来看的话也不复杂,第一部分^(chr[^:]+):,首先匹配一行的开始,接着匹配()里面的一切。总结起来就是该部分匹配以chr开头以及至少一个非:的字符,一次匹配到:就结束了。第二部分和第三部分都是匹配至少一个数字。最后将匹配到的三部分形成三列。 要实现这一功能还有sed很多方法,比如我们只需要将:和-替换成一个制表符就行了:
$ echo 'chr1:28427874-28425431'|sed 's/[:-]/\t/g'
chr1 28427874 28425431
还可以拆成多个命令完成:
$ echo 'chr1:28427874-28425431'|sed 's/:/\t/g' | sed 's/-/\t/g'
chr1 28427874 28425431
还可以通过-e选项来添加多个命令
$ echo 'chr1:28427874-28425431'|sed -e 's/:/\t/g' -e 's/-/\t/g'
chr1 28427874 28425431
打印特定的几行
这个类似于head,如果我们需要打印第m到n行,使用’m,np’进行匹配
$ sed -n '2,5p' chroms.txt
chrom1 3216025 3216968
chrom1 3216022 3216024
chrom1 3671349 3671498
chrom1 3214482 3216021
删除命令:d命令
删除空白行
$ sed '/^$/d' file
指定删除第几行
比如删除第二行
$ cat company.txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
$ sed '2d' company.txt
baidu 100 5000
google 110 5000
guge 50 3000
删除指定的第几行以及后面所有行
比如删除第二行及其后面所有行
$ sed '2,$d' company.txt
baidu 100 5000
从上面很容易知道$d表示最后一行,同时删除第m行到第n行也很容易实现了
#删除最后一行
$ sed '$d' company.txt
baidu 100 5000
sohu 100 4500
google 110 5000
#删除第2到3行
$ sed '2,3d' company.txt
baidu 100 5000
guge 50 3000
匹配删除
比如我们需要删除所有开头是g的行
$ sed '/^g/'d company.txt
baidu 100 5000
sohu 100 4500
注意这里之间匹配用'‘围住,d则不用
已匹配字符串标记&
啥意思呢,就是&代表已匹配的项
$ sed 's/\w\+/[&]/g' company.txt
[baidu] [100] [5000]
[sohu] [100] [4500]
[google] [110] [5000]
[guge] [50] [3000]
正则表达式\w\+匹配每一个单词,使用[&]替换它,&对应于之前匹配到的每个单词
子串匹配标记\1
即匹配给定样式的其中一部分,对于匹配到的第一个子串就标记为\1,以此类推匹配到的第二个子串就是\2
$ echo this is digit 7 in a number|sed 's/digit \([0-9]\)/\1/'
this is 7 in a number
\(..\)用于匹配子串数字,上述命令中digit 7被匹配到的是子串是7 再举个例子
$ echo aaa BBB |sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
BBB aaa
上述命令中匹配到的子串分别是aaa、BBB,\2表示BBB,\1表示aaa。
引用
sed表达式可以使用单引号来引用,但是如果表达式内部包含变量字符串,就需要使用双引号。
test=hello
echo hello WORLD | sed "s/$test/HELLO"
HELLO WORLD
下一个:n命令
如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行然后继续
$ sed '/test/{ n; s/aa/bb/; }' file
变形:y命令
把1~10行内所有的abcde转为大写,注意正则表达式元字符不能使用该命令:
$ sed '1,10y/abcde/ABCDE/' file
退出:q命令
打印完第10行后退出sed
$ sed '10q' file
打印奇数行或者偶数行
有两种方法:
#奇数行
$ $ sed -n 'p;n' company.txt
baidu 100 5000
google 110 5000
#偶数行
$ sed -n 'n;p' company.txt
sohu 100 4500
guge 50 3000
另一种方法
#奇数行
$ sed -n '1~2p' company.txt
baidu 100 5000
google 110 5000
#偶数行
$ sed -n '2~2p' company.txt
sohu 100 4500
guge 50 3000
sed内容十分丰富,这里只是稍微介绍一些主要功能,想要深入学习的话可参考 官方文档