linux 数据处理软件,【shell笔记>文本处理|专项】Linux数据文本处理工具(2)

接1

file 查看文件编码

wsx@wsx-ubuntu:~$ file regular_express.txt

regular_express.txt: ASCII text, with CRLF, LF line terminators

常用的大型数据文件一般存为ASCII码形式(像几大基因bank的数据文件),而我们自己认为创建的常为UTF-8,所以有时候认为处理文件需要会碰到把UTF-8编码的字符插入到ASCII码文件里去了。遇到这种问题,我们可以用hexdump -c命令查看出错的地方(手边没有这样的文件,就不举例了)。

用sort对文本排序

我们先创建一个bed格式文件来试试这个命令:

wsx@wsx-ubuntu:~$ cat test.bed

chr1 26 39

chr3 32 47

chr1 40 50

chr1 9 28

chr2 35 54

chr1 10 19

wsx@wsx-ubuntu:~$ sort test.bed

chr1 10 19

chr1 26 39

chr1 40 50

chr1 9 28

chr2 35 54

chr3 32 47

可以明显看到文本按照第一列进行了排序。

默认,sort用空格或tab键作为域(列)分隔符。如果我们用其他形式的分隔符,需要用-t选项指定。

下面是对bed文件最通用的排序命令:

wsx@wsx-ubuntu:~$ sort -k1,1 -k2,2n test.bed

chr1 9 28

chr1 10 19

chr1 26 39

chr1 40 50

chr2 35 54

chr3 32 47

基本操作bedtools软件都会先用这个命令对bedtools文件排序。

现在略加解释一下,sort用-k选项指定某列的排序方式。而每次使用-k选项都要带上指定列的范围(start, end)。如果只指定一列,就为(start,start)了,像上面命令的-k1,1就是。也许你会觉得-k2,2n很奇怪,这里的n指定程序把第二列当做数值对待。如果不做设定,都是当做字符对待(shell都是这么对待数值数据的)。所以总结其他这一行命令就是对第一列按照字符排序,第二列按照数值排序。

我们可以用-c选项检查一个文件是不是已经按照过某种方式排过序了。

wsx@wsx-ubuntu:~$ sort -k1,1 -k2,2n test.bed | sort -k1,1 -k2,2 -c

sort:-:2:无序: chr1 10 19

wsx@wsx-ubuntu:~$ echo $?

1

wsx@wsx-ubuntu:~$ sort -k1,1 -k2,2n test.bed | sort -k1,1 -k2,2n -c

wsx@wsx-ubuntu:~$ echo $?

0

上面可以清楚地看到sort是怎么对待文件的(一般shell返回0表示成功执行)。

wsx@wsx-ubuntu:~$ tsfds

tsfds:未找到命令

wsx@wsx-ubuntu:~$ echo $?

127

wsx@wsx-ubuntu:~$ echo test

test

wsx@wsx-ubuntu:~$ echo $?

0

shell的命令退出状态码表示了该命令执行的完成的某种情况。不同的状态码有不同的含义,具体可以百度查阅(我之前整理的shell笔记应该讲过,可以看看)。

反向排序用-r选项。如果你只想反转一列,可以把它加在-k选项后。

wsx@wsx-ubuntu:~$ sort -k1,1 -k2,2nr test.bed

chr1 40 50

chr1 26 39

chr1 10 19

chr1 9 28

chr2 35 54

chr3 32 47

现在我给test.bed加一行:

wsx@wsx-ubuntu:~$ cat test.bed

chr1 26 39

chr3 32 47

chr1 40 50

chr1 9 28

chr2 35 54

chr1 10 19

chr11 22 56

你会发现有点奇怪

wsx@wsx-ubuntu:~$ sort -k1,1 -k2,2n test.bed

chr1 9 28

chr1 10 19

chr1 26 39

chr1 40 50

chr11 22 56

chr2 35 54

chr3 32 47

怎么chr11在chr2前面?其实sort排序的方式有点像查字典。例子中,命令先比较c,然后比较h,然后比较r,接着比较1,自然11会在2前面了。这里可以添加V选项修改。

wsx@wsx-ubuntu:~$ sort -k1,1V -k2,2n test.bed

chr1 9 28

chr1 10 19

chr1 26 39

chr1 40 50

chr2 35 54

chr3 32 47

chr11 22 56

是不是觉得这样更可观一些?不过通常在处理数据时不做此处理,符合 规范的数据可以让后续处理程序效率更高。

基本掌握sort这些也够用了,它主要为后续处理服务。如果想知道其他的用法,查查吧,同时欢迎发文来交流。

用uniq寻找唯一值

首先创建样例文本

wsx@wsx-ubuntu:~$ cat test.letter

A

A

B

C

B

C

C

C

D

F

D

使用uniq看看

wsx@wsx-ubuntu:~$ uniq test.letter

A

B

C

B

C

D

F

D

尼玛,怎么不对。它好像只去掉了连续的同一字符。怎么办?想想我们刚学了什么命令?sort不是刚好可以把同样的字符弄到一起去吗,然后再使用uniq,嘿嘿:

wsx@wsx-ubuntu:~$ sort test.letter | uniq

A

B

C

D

F

哟呵,got you。

加-c选项计数:

wsx@wsx-ubuntu:~$ sort test.letter | uniq -c

2 A

2 B

4 C

2 D

1 F

把结果再排序

wsx@wsx-ubuntu:~$ sort test.letter | uniq -c | sort -rn

4 C

2 D

2 B

2 A

1 F

-d选项只输出重复行

wsx@wsx-ubuntu:~$ cat test.letter

A

A

B

C

B

C

C

C

D

F

D

wsx@wsx-ubuntu:~$ uniq -d test.letter

A

C

wsx@wsx-ubuntu:~$ sort test.letter | uniq -d

A

B

C

D

使用时需要注意处理不同导致的结果差异。

Join 命令

用来连接文件。

假设现在我们有两个文件:

wsx@wsx-ubuntu:/tmp$ cat example.bed

chr1 26 39

chr1 32 47

chr3 11 28

chr1 40 49

chr3 16 27

chr1 9 28

chr2 35 53

wsx@wsx-ubuntu:/tmp$ cat example_length.txt

chr1 53453

chr2 34356

chr3 24356

我想把第二个文件说明染色体长度添加到第一个文件对应染色体的第三列。

我们首先要给文件排序(使用join前必须做),然后使用join命令。

wsx@wsx-ubuntu:/tmp$ sort -k1,1 example.bed > example_sorted.bed

wsx@wsx-ubuntu:/tmp$ sort -c -k1,1 example_length.txt

wsx@wsx-ubuntu:/tmp$ cat example_sorted.bed

chr1 26 39

chr1 32 47

chr1 40 49

chr1 9 28

chr2 35 53

chr3 11 28

chr3 16 27

wsx@wsx-ubuntu:/tmp$ join -1 1 -2 1 example_sorted.bed example_length.txt > example_with_length.txt

wsx@wsx-ubuntu:/tmp$ cat example_with_length.txt

chr1 26 39 53453

chr1 32 47 53453

chr1 40 49 53453

chr1 9 28 53453

chr2 35 53 34356

chr3 11 28 24356

chr3 16 27 24356

命令基本语法是

join -1 -2

既然名字叫join,就是两者必须有共同之处,通过共同的支点将两者连为一体。

-1和-2选项后接参数分别指定了这个支点,也就是连接的域(列)。比如例子中,都是两个文件的第一列。

两个文件中,第一列都共有chr1(2)(3)。 如果不一致会出现什么情况呢?

wsx@wsx-ubuntu:/tmp$ join -1 1 -2 1 example_sorted.bed example_length_alt.txt chr1 26 39 53453

chr1 32 47 53453

chr1 40 49 53453

chr1 9 28 53453

chr2 35 53 34356

如果第二个文件没有chr3,join之后也没了!!

我们可以通过-a选项指定哪一个文件可以不遵循配对

wsx@wsx-ubuntu:/tmp$ join -1 1 -2 1 -a 1 example_sorted.bed example_length_alt.txt

chr1 26 39 53453

chr1 32 47 53453

chr1 40 49 53453

chr1 9 28 53453

chr2 35 53 34356

chr3 11 28

chr3 16 27

awk

awk是文本处理的一把好手,虽然它不能像python,R干一些高级复杂的主题工作,但是它具备完整的命令操作和编程体系。

awk是一门语言,我不可能在学习的时候能够逻辑清晰详细地介绍给大家。主要是还通过实例来了解用法,加深认识。手册可以参考http://man.linuxde.net/awk。

首先要明白的是,awk按行处理数据。在shell知识里,如果把一个文档看做一张表。那么一行就是一个记录,一列就是一个域。可以看出,awk就是按记录处理文本的。

其次是awk的程序结构是

pattern {action}

pattern可以是表达式或者正则表达式。pattern有点像if语句,当它满足时就会执行相应的动作。

另一个awk核心是它用$0表示所有列,$1,$2...等等表示对应的列。我们可以很方便地用它进行操作。

wsx@wsx-ubuntu:/tmp$ awk '{print $0}' example.bed

chr1 26 39

chr1 32 47

chr3 11 28

chr1 40 49

chr3 16 27

chr1 9 28

chr2 35 53

wsx@wsx-ubuntu:/tmp$ awk '{print $1}' example.bed

chr1

chr1

chr3

chr1

chr3

chr1

chr2

wsx@wsx-ubuntu:/tmp$ awk '{print $2}' example.bed

26

32

11

40

16

9

print语句就像动作一样输出你操作的结果。

wsx@wsx-ubuntu:/tmp$ awk '{ print $2 "\t" $3}' example.bed

26 39

32 47

11 28

40 49

16 27

9 28

35 53

wsx@wsx-ubuntu:/tmp$ awk '{ print $2 $3}' example.bed

2639

3247

1128

4049

1627

928

3553

wsx@wsx-ubuntu:/tmp$ awk '{ print $2 , $3}' example.bed

26 39

32 47

11 28

40 49

16 27

9 28

35 53

了解上述几个语句的不同。

表示染色体名一般用带chr或者不带chr标志两种方式。当我们要用到这两种时,肯定要让它们能够对应起来,也就是转换。awk命令可以非常方便地添加chr标记。

下面我先把例子文件的chr去掉,然后加上试试。

wsx@wsx-ubuntu:/tmp$ awk '{ print $1}' example.bed

chr1

chr1

chr3

chr1

chr3

chr1

chr2

wsx@wsx-ubuntu:/tmp$ awk '{ print $1}' example.bed | cut -c4

1

1

3

1

3

1

2

wsx@wsx-ubuntu:/tmp$ awk '{ print $1}' example.bed | cut -c4 | awk '{print "chr"$1}'

chr1

chr1

chr3

chr1

chr3

chr1

chr2

awk作为一门编程语言,它支持各种操作符(运算,逻辑,判断)喔。

wsx@wsx-ubuntu:/tmp$ awk '$3 - $2 >18' example.bed

chr1 9 28

wsx@wsx-ubuntu:/tmp$ awk '$1 ~/chr1/ && $3 - $2 > 10' example.bed

chr1 26 39

chr1 32 47

chr1 9 28

# 这里 ~ 符号用来匹配正则表达式

还有awk存在一些变量,像NR表示行号,OFS表示输出分隔符等。

wsx@wsx-ubuntu:/tmp$ awk 'NR >= 3 && NR <= 5' example.bed

chr3 11 28

chr1 40 49

chr3 16 27

如果我们想把gtf文件转换成为bed格式,可以使用

wsx@wsx-ubuntu:~/Work/research/Promoter_Research$ head -n1000 Homo_sapiens.GRCh37.75.gtf | awk '!/^#/{ print $1 "\t" $4-1 "\t" $5} ' | head -n 3

1 11868 14412

1 11868 14409

1 11868 12227

因为篇幅有限,我不可能输出所有结果,所以只取部分数据做了运算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值