Linux学习笔记(九)

mark

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内容十分丰富,这里只是稍微介绍一些主要功能,想要深入学习的话可参考 官方文档

注: 本文参考了sed的 官方文档以及Linux命令大全中的 sed命令用法

Researcher

I am a PhD student of Crop Genetics and Breeding at the Zhejiang University Crop Science Lab. My research interests covers a range of issues:Population Genetics Evolution and Ecotype Divergence Analysis of Oilseed Rape, Genome-wide Association Study (GWAS) of Agronomic Traits.

comments powered by Disqus