Linux bash学习
来源:互联网 发布:什么是奥菲斯软件 编辑:程序博客网 时间:2024/05/20 07:49
更多生信和LInux学习,程序写作,请扫描关注生信宝典。
https://mp.weixin.qq.com/mp/homepage?__biz=MzI5MTcwNjA4NQ==&hid=6&sn=667813e1f021e2cf155a74457b48d087&scene=18&uin=&key=&devicetype=Windows+UnKnow&version=62040549&lang=zh_CN&ascene=7&winzoom=1
本教程宗旨 (请仔细阅读)
本教程不是一个完备的Linux使用教程,而是侧重于一般教程默认读者会了的信息,包括基本概念的解释 (方便初学者了解自己的操作)、命令的各种错误及解决 (通常写教程的都是对这一领域比较熟悉的,一般不会提到这些初学者刚开始不好理解的简单错误)、部分常用命令 (会提到基本用法,具体的使用还请查看手册或在线搜索)、常用快捷键 (简化操作)和组合命令 (快速的批处理等,初学者一般不会想到、高级学者又不屑于提起的部分)。
为什么要用Linux系统
个人认为,Linux操作系统和类Linux操作系统的命令行界面是最适合进行生物信息分析的操作系统。原因有三点:
- 长期运行的稳定性
- 多数软件只有Linux版本
- 强大的Bash命令简化繁琐的操作,尤其是大大简化重复性工作
但对于初学者来说,接触和理解Linux操作系统需要一些时间和摸索。陡然从可视化点选操作的Windows进入到只有命令行界面的Linux,最大的陌生感是不知道做什么,不知道文件在哪?本文希望能通过几个示例帮助大家适应Linux系统。
如何获取Linux系统
- 如果自己的单位有共有服务器,可以尝试申请账号。
- 自己的电脑安装双系统或虚拟机
- 购买一块云服务器
- 试验下在线学习平台实验楼 https://www.shiyanlou.com (里面也有不少Linux教程,任意点一个进去,双击桌面的
Xfce
图标,都可以启动Linux终端) - <生信宝典>微信公众号后台回复向管理员索要
初识Linux系统
登录Linux系统后,呈现在眼前的是这样一个界面:
Last login: Mon Jun 5 16:56:56 2017 from 219.241.208.209Welcome to aliyun Elastic Compute Service!ct@ehbio:~$
首先解释下出现的这几个字母和符号:
ct
: 用户名ehbio
:如果是登录的远程服务器,则为宿主机的名字~
: 代表家目录, 在我们进入新的目录后,这个地方会跟着改变$
: 用来指示普通用户输入命令的地方;对根用户来说一般是#
- http://bashrcgenerator.com/可视化定制不同的显示方式。
我的电脑在哪?
打开Windows,首先看到的是桌面;不爱整理文件的我,桌面的东西已经多到需要2个屏幕才能显示的完。另外一个常用的就是我的电脑,然后打开D盘,依次点开对应的文件夹,然后点开文件。
Linux的文件系统组织方式与Windows略有不同,登录进去就是家目录,可视为Windows下的桌面。在这个目录下,我们可以新建文件、新建文件夹,就像在桌面上的操作一样。
注:
- 这里我们假设所有用到的文件和文件夹都放置于家目录下
- Linux的家目录严格来说可能类似于Windows下的
C:\Users\ct
如果想查看当前目录下都有什么内容,输入命令 ls
,回车即可 (ls可以理解为单词list的缩写)。当前目录下什么也没有,所以没有任何输出。
ct@ehbio:~$ ls
如果错把l
看成了i
,输入了is
,则会出现下面的提示未找到命令
。如果输入的是Linux基本命令,出现这个提示,基本可以判定是命令输入错了,瞪大眼睛仔细看就是了。 在敲完命令回车后,注意查看终端的输出,以判断是否有问题。
ct@ehbio:~$ is-bash: is: 未找到命令# 大小写敏感ct@ehbio:~$ lS-bash: lS: 未找到命令
当前目录下只有一个文件,看不出效果,我们可以新建几个文件和文件夹,来查看下。
mkdir
是新建一个目录 (m
ak
e a dir
ectory);data
是目录的名字。
如果目录存在,则会出现提示,”无法创建已存在的目录”。这时可以使用参数-p
忽略这个错误。
ct@ehbio:~$ mkdir datact@ehbio:~$ mkdir lsdatact@ehbio:~$ mkdir datamkdir: 无法创建目录"data" : 文件已存在ct@ehbio:~$ mkdir -p data
cat
是一个命令,主要用来查看文件;在这与<<END
连用用于读入大段数据。输入cat <<END
之后,回车,会看到终端出现一个大于号,大于号后面可以输入内容,再回车,继续输入内容,直到我们输入END
(大写的,与上面一致),输入过程结束,我们输入的内容都显示在了屏幕上。
ct@ehbio:~$ mkdir datact@ehbio:~$ cat <<END> a> bc> ENDabc`>`是一个重定向符号,即把前面命令的输出写入到`>`后面的文件中。如下所示,新建了一个`Fasta`格式的文件。`ls -l`列出文件的详细信息;`-l`表示命令行参数,是程序预留的一些选项,保证在不更改程序的情况下获得更灵活的操作。可使用`man ls`查看`ls`所有的命令行参数, 上下箭头翻页,按`q`退出查看。(man: manual, 手册)```bashct@ehbio:~$ cat <<END >data/test.fa> >SOX2> ACGTCGGCGGAGGGTGGSCGGGGGGGGAGAGGT> ACGATGAGGAGTAGGAGAGAGGAGG> >OCT4> ACGTAGGATGGAGGAGAGGGAGGGGGGAGGAGAGGAA> AGAGTAGAGAGA> >NANOG> ACGATGCGATGCAGCGTTTTTTTTTGGTTGGATCT> CAGGTAGGAGCGAGGAGGCAGCGGCGGATGCAGGCA> ACGGTAGCGAGTC> >mYC HAHA> ACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGC> CAGGACAGGAGCTA> end> END<div class="se-preview-section-delimiter"></div>## 注意命令和参数之间的空格ct@ehbio:~/data$ ls-l-bash: ls-l: 未找到命令ct@ehbio:~$ ls -l总用量 4<div class="se-preview-section-delimiter"></div>## d: dir; 表示data是个目录<div class="se-preview-section-delimiter"></div>## rwx:表示目录的权限,暂时忽略,或自己在线搜索drwxrwxr-x 2 ct ct 4096 6月 8 14:52 datact@ehbio:~$ ls -l data总用量 4<div class="se-preview-section-delimiter"></div>## 开头的`-`表示test.fa是个文件-rw-rw-r-- 1 ct ct 284 6月 8 14:48 test.fa<div class="se-preview-section-delimiter"></div>
查看写入的文件的内容,cat 文件名
;需要注意的是文件所在的目录,默认是当前目录;如下面第一个命令,会提示cat: test.fa: 没有那个文件或目录
,是因为当前目录下不存在文件test.fa
。(注意文件末尾的end)
ct@ehbio:~$ cat test.facat: test.fa: 没有那个文件或目录ct@ehbio:~$ cat data/test.fa >SOX2ACGTCGGCGGAGGGTGGSCGGGGGGGGAGAGGTACGATGAGGAGTAGGAGAGAGGAGG>OCT4ACGTAGGATGGAGGAGAGGGAGGGGGGAGGAGAGGAAAGAGTAGAGAGA>NANOGACGATGCGATGCAGCGTTTTTTTTTGGTTGGATCTCAGGTAGGAGCGAGGAGGCAGCGGCGGATGCAGGCAACGGTAGCGAGTC>mYC HAHAACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
test.fa
在目录data
下,可以先进入data
目录,然后再查看文件。类比于Windows下先点开一个文件夹,再点开下面的文件。
cd
(change dir)切换目录。
head
查看文件最开始的几行,默认为10行,可使用-n 6
指定查看前6行。
ct@ehbio:~$ cd datact@ehbio:~/data$ head -n 6 test.fa >SOX2ACGTCGGCGGAGGGTGGSCGGGGGGGGAGAGGTACGATGAGGAGTAGGAGAGAGGAGG>OCT4ACGTAGGATGGAGGAGAGGGAGGGGGGAGGAGAGGAAAGAGTAGAGAGA<div class="se-preview-section-delimiter"></div>
另外less
和more
也可以用来查看文件,尤其是文件内容特别多的时候。
ct@ehbio:~/data$ less test.fa <div class="se-preview-section-delimiter"></div># q: 退出<div class="se-preview-section-delimiter"></div># 上下箭头、空格翻页<div class="se-preview-section-delimiter"></div>
获取可用命令行参数
前面使用的命令,有几个用到了参数如ls -l
, head -n 6
等,需要注意的是命令跟参数之间要有空格。
终端运行man ls
可以查看ls
所有可用的参数,上下箭头翻页,按q
退出查看。(man: manual, 手册)
ct@ehbio:~/data$ man lsNAME ls - list directory contentsSYNOPSIS ls [OPTION]... [FILE]...DESCRIPTION List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor --sort is specified. Mandatory arguments to long options are mandatory for short options too. -a, --all do not ignore entries starting with . -A, --almost-all do not list implied . and .. --author with -l, print the author of each file -b, --escape print C-style escapes for nongraphic characters ....<div class="se-preview-section-delimiter"></div>
文件上下翻转和左右翻转
两个有意思的命令,tac
: 文件翻转,第一行变为最后一行,第二行变为倒数第二行;rev
每列反转,第一个字符变为最后一个字符,第二个字符变为倒数第二个字符。
ct@ehbio:~/data$ cat <<END | tac> first> second> third> ENDthirdsecondfirstct@ehbio:~/data$ cat <<END | rev> abcde> xyz> ENDedcbazyx<div class="se-preview-section-delimiter"></div>
其它新建文件的方式
nano
类似于Windows下记事本的功能,nano filename
就可以新建一个文件,并在里面写内容;ctrl+x
退出,根据提示按Y
保存。
vim
功能更强大的文本编辑器。vim filename
就可以新建一个文件, 敲击键盘字母i
,进入写作模式。写完后,敲击键盘Esc
, 退出写作模式,然后输入:w
(会显示在屏幕左下角),回车保存。vim
的常用方法,以后会单写一个,这里点到为止。
Linux下文件操作
常用的文件操作有移动文件到另一个文件夹、复制文件到另一个文件夹、文件重命名等。
cp
(copy): 拷贝文件或文件夹 (cp -r
拷贝文件夹时的参数,递归拷贝)
<div class="se-preview-section-delimiter"></div># 列出当前目录下有的文件和文件夹ct@ehbio:~$ lsdata<div class="se-preview-section-delimiter"></div># 新建一个文件夹ct@ehbio:~$ mkdir ehbio_project<div class="se-preview-section-delimiter"></div># 列出当前目录下有的文件和文件夹, 及其子文件夹的内容<div class="se-preview-section-delimiter"></div># data目录下有一个文件,ehbio_project目录下无文件ct@ehbio:~$ ls *data:test.faehbio_project:<div class="se-preview-section-delimiter"></div># 拷贝data目录下的文件test.fa到ehbio_project目录下ct@ehbio:~$ cp data/test.fa ehbio_project/<div class="se-preview-section-delimiter"></div># 列出当前目录下有的文件和文件夹, 及其子文件夹的内容<div class="se-preview-section-delimiter"></div># data目录下有一个文件,ehbio_project目录下无文件ct@ehbio:~$ ls *data:test.faehbio_project:test.fa<div class="se-preview-section-delimiter"></div>
mv
(move): 移动文件或文件夹
<div class="se-preview-section-delimiter"></div># 重命名data目录下的文件test.fa为first.fa<div class="se-preview-section-delimiter"></div># mv除了可以移动文件,也可以做单个文件的重命名ct@ehbio:~$ mv data/test.fa data/first.fa<div class="se-preview-section-delimiter"></div># 列出当前目录下有的文件和文件夹, 及其子文件夹的内容ct@ehbio:~$ ls *data:first.faehbio_project:test.fa<div class="se-preview-section-delimiter"></div>
rename
: 文件重命名 (常用于批量重命名,不同的系统可能用法略有不同,使用前先man rename
查看使用方法)
<div class="se-preview-section-delimiter"></div># 进入另一个目录ct@ehbio:~$ cd ehbio_project/ct@ehbio:~/ehbio_project$ lstest.fa<div class="se-preview-section-delimiter"></div># 给文件做一份拷贝ct@ehbio:~/ehbio_project$ cp test.fa second.fact@ehbio:~/ehbio_project$ lssecond.fa test.fa<div class="se-preview-section-delimiter"></div># 给文件多拷贝几次,无聊的操作,就是为了给rename提供发挥作用的机会ct@ehbio:~/ehbio_project$ cp test.fa test2.fact@ehbio:~/ehbio_project$ cp test.fa test3.fact@ehbio:~/ehbio_project$ cp test.fa test4.fa<div class="se-preview-section-delimiter"></div># cp 后面需要2个参数,被拷贝的文件和要被拷贝到的目录或文件<div class="se-preview-section-delimiter"></div># 出现下面的错误,表示缺少目标路径或文件ct@ehbio:~/ehbio_project$ cp ehbio.fa cp: 在" ehbio.fa" 后缺少了要操作的目标文件Try 'cp --help' for more information.ct@ehbio:~/ehbio_project$ lssecond.fa test2.fa test3.fa test4.fa test.fa<div class="se-preview-section-delimiter"></div># 用rename进行文件批量重命名ct@ehbio:~/ehbio_project$ rename 'test' 'ehbio' test*.fact@ehbio:~/ehbio_project$ lsehbio2.fa ehbio3.fa ehbio4.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div>
ln
(link): 给文件建立快捷方式 (ln -s source_file target
创建软连接)。
在建立软连接时,原文件要使用全路径。全路径指以/
开头的路径。
建立软连接,是为了在不增加硬盘存储的情况下,简化文件访问方式的一个办法。把其它文件夹下的文件链接到当前目录,使用时只需要写文件的名字就可以了,不需要再写长串的目录了。
../
: 表示上一层目录;../../
: 表示上面两层目录
pwd
(print current/working directory): 输出当前所在的目录
\``为键盘
Esc下第一个按键 (与家目录
~`符号同一个键),写在反引号内的命令会被运行,运行结果会放置在反引号所在的位置
<div class="se-preview-section-delimiter"></div># 建立软连接,把当前目录下的ehbio2.fa,链接到上一层目录的data下面<div class="se-preview-section-delimiter"></div># 这是一个无效的软连接,ct@ehbio:~/ehbio_project$ ln -s ehbio2.fa ../data<div class="se-preview-section-delimiter"></div># 在使用ls查看时,无效的软连接的文件名下面是黑色的背景。ct@ehbio:~/ehbio_project$ ls -l ../data/总用量 4lrwxrwxrwx 1 ct ct 9 6月 9 17:55 ehbio2.fa -> ehbio2.fa-rw-rw-r-- 1 ct ct 284 6月 8 14:48 first.fa<div class="se-preview-section-delimiter"></div># 输出当前所在的目录ct@ehbio:~/ehbio_project$ pwd/home/ct/ehbio_project<div class="se-preview-section-delimiter"></div># 建立软连接时,原始文件一定使用全路径。全路径指以/开头的路径。ct@ehbio:~/ehbio_project$ ln -s /home/ct/ehbio_project/ehbio2.fa ../dataln: 无法创建符号链接" ../data/ehbio2.fa" : 文件已存在<div class="se-preview-section-delimiter"></div># 上面的错误信息时,已经存在这么一个链接了(虽然是无效的),但再建新的链接时还会提示<div class="se-preview-section-delimiter"></div># 使用`-f` (force)强制覆盖已有的链接ct@ehbio:~/ehbio_project$ ln -fs `pwd`/ehbio2.fa ../data<div class="se-preview-section-delimiter"></div># 再次查看时,就正常了。文件名下面没有了背景色,并且有个右箭头指向原始文件<div class="se-preview-section-delimiter"></div># `lrwxrwxrwx`中的`l`表示软连接。ct@ehbio:~/ehbio_project$ ls -l ../data/总用量 4lrwxrwxrwx 1 ct ct 32 6月 9 17:56 ehbio2.fa -> /home/ct/ehbio_project/ehbio2.fa-rw-rw-r-- 1 ct ct 284 6月 8 14:48 first.fa<div class="se-preview-section-delimiter"></div># 通常为了简化写法,使用`pwd`代替全路径<div class="se-preview-section-delimiter"></div># `为键盘Esc下面的按键,写在反引号内的命令会被运行,运行结果会放置在反引号所在的位置ct@ehbio:~/ehbio_project$ ln -s `pwd`/ehbio2.fa ../dataln: 无法创建符号链接" ../data/ehbio2.fa" : 文件已存在ct@ehbio:~/ehbio_project$ ln -fs `pwd`/ehbio2.fa ../datact@ehbio:~/ehbio_project$ ls -l ../data/总用量 4lrwxrwxrwx 1 ct ct 32 6月 9 17:56 ehbio2.fa -> /home/ct/ehbio_project/ehbio2.fa-rw-rw-r-- 1 ct ct 284 6月 8 14:48 first.fa<div class="se-preview-section-delimiter"></div>
Linux下命令的一些异常情况
命令不全:在命令没有输入完 (引号或括号没有配对),就不小心按下了Enter
键,终端会提示出一个>
代表命令不完整,这是可以继续输入,也可以ctrl+c
终止输入,重新再来。(下面sed命令使用时,还有另外一种命令不全的问题)
ct@ehbio:~/ehbio_project$ rename 'ehbio2>'ct@ehbio:~/ehbio_project$ rename 'ehbio2> ^Cct@ehbio:~/ehbio_project$<div class="se-preview-section-delimiter"></div>
文件名输入错误: 多一个字母、少一个字母、大小写问题
ct@ehbio:~/ehbio_project$lsehbio2.fa ehbio3.fa ehbio4.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div># 重命名没有生效ct@ehbio:~/ehbio_project$ rename 'ehbio2' 'ehbio5' ebio2.fact@ehbio:~/ehbio_project$ lsehbio2.fa ehbio3.fa ehbio4.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div># 仔细看是ehbio2.fa写成了ebio2.fa,更正后即可。Z8vb3e9jtel4m99ss6e7eZ:~/ehbio_project$ rename 'ehbio2' 'ehbio5' ehbio2.fact@ehbio:~/ehbio_project$ lsehbio3.fa ehbio4.fa ehbio5.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div>
所在目录不对: 访问的文件不存在于当前目录,而又没有提供绝对路径, 或软连接失效
ct@ehbio:~/ehbio_project$ lsehbio3.fa ehbio4.fa ehbio5.fa ehbio6.fa ehbio.fa second.fact@ehbio:~/ehbio_project$ ls ../dataehbio2.fa first.fa<div class="se-preview-section-delimiter"></div># 当前目录没有ehbio2.fact@ehbio:~/ehbio_project$ less ehbio2.faehbio2.fa: 没有那个文件或目录<div class="se-preview-section-delimiter"></div># ehbio2.fa在上一层目录的data目录下ct@ehbio:~/ehbio_project$ ls ../data/ehbio2.fa ../data/ehbio2.fa<div class="se-preview-section-delimiter"></div># 加上路径依然访问不了 ct@ehbio:~/ehbio_project$ less ../data/ehbio2.fa ../data/ehbio2.fa: 没有那个文件或目录<div class="se-preview-section-delimiter"></div># 上面的问题是软连接失效,在之前的操作中删掉了原始的ehbio2.fa,所以快捷方式失效<div class="se-preview-section-delimiter"></div># 正确的访问ct@ehbio:~/ehbio_project$ tail -n 3 ../data/first.fa ACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
Linux下文件内容操作
常用的文件内容操作有文件压缩解压缩、文件大小行数统计、文件内容查询等。
gzip
: 压缩文件; gunzip
: 解压缩文件
<div class="se-preview-section-delimiter"></div># gzip -c 把压缩的文件输出到标准输出 (一般是屏幕)<div class="se-preview-section-delimiter"></div># '>' 输出重定向,输出写入文件ct@ehbio:~/ehbio_project$ gzip -c ehbio.fa >ehbio.fa.gz<div class="se-preview-section-delimiter"></div># 多了一个.gz文件ct@ehbio:~/ehbio_project$ lsehbio3.fa ehbio4.fa ehbio5.fa ehbio.fa ehbio.fa.gz second.fa<div class="se-preview-section-delimiter"></div>#解压缩ct@ehbio:~/ehbio_project$ gunzip ehbio.fa.gzgzip: ehbio.fa already exists; do you wish to overwrite (y or n)? yct@ehbio:~/ehbio_project$ lsehbio3.fa ehbio4.fa ehbio5.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div>
wc
(word count): 一般使用wc -l
获取文件的行数
<div class="se-preview-section-delimiter"></div># 输出文件有14行ct@ehbio:~/ehbio_project$ wc -l ehbio.fa14 ehbio.fa<div class="se-preview-section-delimiter"></div>
获取文件中包含大于号 (>
)的行, grep
(print lines matching a pattern)。 grep
的用法很多,支持正则表达式匹配,这里不展开,可以自己查阅资料,或在后期的教程涉及到时再学习。
ct@ehbio:~/ehbio_project$ grep '>' ehbio.fa>SOX2>OCT4>NANOG>mYC HAHA<div class="se-preview-section-delimiter"></div># 获取包含>的行的行数 (-c: count lines)ct@ehbio:~/ehbio_project$ grep -c '>' ehbio.fa4<div class="se-preview-section-delimiter"></div># 是不是还记得当时新建文件时,末尾多了一行end,删除end所在行ct@ehbio:~/ehbio_project$ less ehbio.fa <div class="se-preview-section-delimiter"></div># -v: 不输出匹配上的行ct@ehbio:~/ehbio_project$ grep -v 'end' ehbio.fa >ehbio6.fact@ehbio:~/ehbio_project$ cat ehbio6.fa >SOX2ACGTCGGCGGAGGGTGGSCGGGGGGGGAGAGGTACGATGAGGAGTAGGAGAGAGGAGG>OCT4ACGTAGGATGGAGGAGAGGGAGGGGGGAGGAGAGGAAAGAGTAGAGAGA>NANOGACGATGCGATGCAGCGTTTTTTTTTGGTTGGATCTCAGGTAGGAGCGAGGAGGCAGCGGCGGATGCAGGCAACGGTAGCGAGTC>mYC HAHAACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTA<div class="se-preview-section-delimiter"></div>
替换文件中的字符: sed
是一个功能强大的文件内容编辑工具,常用于替换、取得行号等操作。
<div class="se-preview-section-delimiter"></div># 第一个错误,漏掉了文件名<div class="se-preview-section-delimiter"></div># 程序静止在这,等待用户的进一步输入<div class="se-preview-section-delimiter"></div># ctrl+c杀掉当前命令ct@ehbio:~/ehbio_project$ sed 's/ HAHA//' | tail -n 3^C<div class="se-preview-section-delimiter"></div># 第二个错误,文件名和单引号之间没有空格,使得sed判断命令错误ct@ehbio:~/ehbio_project$ sed 's/ HAHA//'ehbio.fa | tail -n 3sed:-e 表达式 #1,字符 11:“s”的未知选项<div class="se-preview-section-delimiter"></div># 正确操作,ct@ehbio:~/ehbio_project$ sed 's/ HAHA//' ehbio.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
另外一个方式,去除HAHA
,使用cut
命令 (cut更适合与矩阵操作,去除其中的一列或者多列)。
-f
: 指定取出哪一列,使用方法为-f 2
(取出第2列),-f 2-5
(取出第2-5列),-f 2,5
(取出第2和第5列)。
-d
: 设定分隔符, 默认为TAB键。如果一行没有指定的分隔符,整行都为第一列。
ct@ehbio:~/ehbio_project$ cut -f 1 -d ' ' ehbio.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
Linux终端常用快捷操作
- 命令或文件名自动补全:在输入命令或文件名的前几个字母后,按
Tab
键,系统会自动补全或提示补全 - 上下箭头:使用上下箭头可以回溯之前的命令,增加命令的重用,减少输入工作量
!
加之前输入过的命令的前几个字母,快速获取前面的命令
ct@ehbio:~/ehbio_project$ cut -f 1 -d ' ' ehbio.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAendct@ehbio:~/ehbio_project$ man cut<div class="se-preview-section-delimiter"></div># 直接跳到上面运行的cut命令,再执行一次ct@ehbio:~/ehbio_project$ !cutcut -f 1 -d ' ' ehbio.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
ctrl+a
回到命令的行首,用于修改常命令或注释掉命令
<div class="se-preview-section-delimiter"></div># 写完下面的命令,突然不想运行了,又不想一个个删掉ct@ehbio:~/ehbio_project$ cut -f 1 -d ' ' ehbio.fa | tail -n 4<div class="se-preview-section-delimiter"></div># 按ctrl+a, 回到行首,再输入`#`号,回车,命令即被注释掉。ct@ehbio:~/ehbio_project$ #cut -f 1 -d ' ' ehbio.fa | tail -n 4<div class="se-preview-section-delimiter"></div>
!!
表示上一条命令。
ct@ehbio:~/ehbio_project$ lsehbio3.fa ehbio4.fa ehbio5.fa ehbio6.fa ehbio.fa second.fact@ehbio:~/ehbio_project$ !!lsehbio3.fa ehbio4.fa ehbio5.fa ehbio6.fa ehbio.fa second.fa<div class="se-preview-section-delimiter"></div>
- 替换上一个命令中的字符,再运行一遍命令,用于需要对多个文件执行同样的命令,又不想写循环的情况
<div class="se-preview-section-delimiter"></div># 输入一个命令ct@ehbio:~/ehbio_project$ #cut -f 1 -d ' ' ehbio.fa | tail -n 4<div class="se-preview-section-delimiter"></div># !!表示上一条命令<div class="se-preview-section-delimiter"></div># :gs表示替换,把上一个命令中全部的ehbio替换为ehbio3; g: global; s: substitutect@ehbio:~/ehbio_project$ !!:gs/ehbio/ehbio3<div class="se-preview-section-delimiter"></div>#cut -f 1 -d ' ' ehbio3.fa | tail -n 4<div class="se-preview-section-delimiter"></div># 替换后效果如上<div class="se-preview-section-delimiter"></div># 去掉命令前的#号ct@ehbio:~/ehbio_project$ cut -f 1 -d ' ' ehbio3.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>## 替换ehbio3为ehbio4,直接运行命令ct@ehbio:~/ehbio_project$ !!:gs/ehbio3/ehbio4cut -f 1 -d ' ' ehbio4.fa | tail -n 4>mYCACGGAGCGAGCTAGTGCAGCGAGGAGCTGAGTCGAGCCAGGACAGGAGCTAend<div class="se-preview-section-delimiter"></div>
Linux下的标准输入、输出、重定向、管道
在Linux系统中,有4个特殊的符号,<
, ‘>’, ‘|’, ‘-‘,在我们处理输入和输出时存在重要但具有迷惑性的作用。
默认Linux的命令的结果都是输出到标准输出,错误信息 (比如命令未找到或文件格式识别错误等) 输出到标准错误,而标准输出和标准错误默认都会显示到屏幕上。
>
表示重定向标准输出,> filename
就是把标准输出存储到文件filename里面。标准错误还是会显示在屏幕上。
2 >&1
表示把标准错误重定向到标准输出。Linux终端用2
表示标准错误,1
表示标准输出。
-
(短横线):表示标准输入,一般用于1个程序需要多个输入的时候。
<
标准输入,后面可以跟可以产生输出的命令,一般用于1个程序需要多个输入的时候。
|
管道符,表示把前一个命令的输出作为后一个命令的输入,前面也有一些展示例子。用于数据在不同的命令之间传输,用途是减少硬盘存取损耗。
下面我们通过一个程序stdout_error.sh
来解释上面的文字,内容如下
<div class="se-preview-section-delimiter"></div>#!/bin/bashecho "I am std output" <div class="se-preview-section-delimiter"></div># 下面是随便写的一个理论上不存在的命令, 理论上会报错的。unexisted_command<div class="se-preview-section-delimiter"></div>
运行这个脚本
<div class="se-preview-section-delimiter"></div># 标准输出和标准错误默认都会显示到屏幕上ct@ehbio:~$ bash stdout_error.sh I am std outputstdout_error.sh: line 5: unexisted_command: command not found<div class="se-preview-section-delimiter"></div># >把结果输入到了文件;标准错误还显示在屏幕上ct@ehbio:~$ bash stdout_error.sh >stdout_error.stdoutstdout_error.sh: line 5: unexisted_command: command not foundct@ehbio:~$ cat stdout_error.stdoutI am std output<div class="se-preview-section-delimiter"></div># >把结果输入到了文件; 2>把标准错误输入到了另一个文件ct@ehbio:~$ bash stdout_error.sh >stdout_error.stdout 2>stdout_error.stderrct@ehbio:~$ cat stdout_error.stderrstdout_error.sh: line 5: unexisted_command: command not found<div class="se-preview-section-delimiter"></div># 标准输出和标准错误写入同一个文件ct@ehbio:~$ bash stdout_error.sh >stdout_error.stdout 2>&1ct@ehbio:~$ cat stdout_error.stdoutI am std outputstdout_error.sh: line 5: unexisted_command: command not found<div class="se-preview-section-delimiter"></div>
下面看管道符和标准输入的使用。
<div class="se-preview-section-delimiter"></div># 管道符的使用<div class="se-preview-section-delimiter"></div># 第一个命令的输出作为第二个的输入<div class="se-preview-section-delimiter"></div># 前面的例子中也有使用<div class="se-preview-section-delimiter"></div># tr: 是用于替换字符的,把空格替换为换行,文字就从一行变为了一列ct@ehbio:~$ echo "1 2 3" | tr ' ' '\n'123<div class="se-preview-section-delimiter"></div># cat命令之前也用过,输出一段文字<div class="se-preview-section-delimiter"></div># diff是比较2个文件的差异的,需要2个参数<div class="se-preview-section-delimiter"></div># - (短横线)表示上一个命令的输出,传递给diff<div class="se-preview-section-delimiter"></div># < 表示其后的命令的输出,也重定向给diffct@ehbio:~$ cat <<END | diff - <(echo "1 2 3" | tr ' ' '\n')> 2> 3> 4> END0a1> 13d3< 4<div class="se-preview-section-delimiter"></div># 如果不使用管道和重定向标准输入,程序是这么写的<div class="se-preview-section-delimiter"></div># 先把第一部分存储为1个文件ct@ehbio:~$ cat <<END >firstfile23> 4> ENDct@ehbio:~$ less firstfile <div class="se-preview-section-delimiter"></div># 再把第二部分存储为1个文件ct@ehbio:~$ echo "1 2 3" | tr ' ' '\n' >secondfile<div class="se-preview-section-delimiter"></div># 然后比较ct@ehbio:~$ diff firstfile secondfile 0a1> 13d3< 4<div class="se-preview-section-delimiter"></div>
管道符的更多应用
ct@ehbio:~$ echo "actg aaaaa cccccg" | tr ' ' '\n' | wc -l3<div class="se-preview-section-delimiter"></div># sed =:先输出行号,再输出每行的内容ct@ehbio:~$ echo "a b c" | tr ' ' '\n' | sed = 1a2b3c<div class="se-preview-section-delimiter"></div># 后面这个命令不太好解释<div class="se-preview-section-delimiter"></div># sed = 同时输出行号<div class="se-preview-section-delimiter"></div># N: 表示读入下一行;sed命令每次只读一行,加上N之后就是缓存了第2行,所有的操作都针对第一行;<div class="se-preview-section-delimiter"></div># s: 替换;把换行符替换为\tct@ehbio:~$ echo "a b c" | tr ' ' '\n' | sed = | sed 'N;s/\n/\t/' 1 a2 b3 c<div class="se-preview-section-delimiter"></div># 后面这个命令不太好解释<div class="se-preview-section-delimiter"></div># sed = 同时输出行号<div class="se-preview-section-delimiter"></div># N: 表示读入下一行;sed命令每次只读一行,加上N之后就是缓存了第2行,所有的操作都针对第一行;<div class="se-preview-section-delimiter"></div># s: 替换;把读取的奇数行行首加一个'>'(偶数行相当于被隐藏了)ct@ehbio:~$ echo "a b c" | tr ' ' '\n' | sed = | sed 'N;s/^/>/' >1a>2b>3c<div class="se-preview-section-delimiter"></div># 把多条序列转成FATSA格式<div class="se-preview-section-delimiter"></div># sed = 同时输出行号<div class="se-preview-section-delimiter"></div># N: 表示读入下一行;sed命令每次只读一行,加上N之后就是缓存了第2行,所有的操作都针对第一行;<div class="se-preview-section-delimiter"></div># s: 替换;把读取的奇数行行首加一个'>'(偶数行相当于被隐藏了)<div class="se-preview-section-delimiter"></div># 于是FASTA格式序列就出来了ct@ehbio:~$ echo "actg aaaaa cccccg" | tr ' ' '\n' | sed = | sed 'N;s/^/>/' >1actg>2aaaaa>3cccccg<div class="se-preview-section-delimiter"></div>
文件的可执行属性和环境变量
Linux下文件有一个特殊的属性即可执行属性,用来指示这个文件是一个可执行的脚本或可以运行的二进制文件。前面所提到的这些命令,都具有可执行属性。
which
: 表示查看命令的路径。一般用于当我们想知道使用的命令来源于什么地方时,比如安装了多个R或多个python,但又分不清用的是哪个时,which
一下,立即明了。在这儿我们用which获取的是可执行的命令所在的路径,进而查看其属性。
ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l "`which cd`"<div class="se-preview-section-delimiter"></div>#rwx: 文件所有者可读、可写、可执行<div class="se-preview-section-delimiter"></div>#r-x: 文件所有者所在组其它成员可读、可执行,不可修改<div class="se-preview-section-delimiter"></div>#r-x: 其它人可读、可执行,不可修改-rwxr-xr-x 1 root root 26 12月 7 2016 /usr/bin/cdct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l "`which mkdir`"-rwxr-xr-x. 1 root root 79768 11月 6 2016 /usr/bin/mkdirct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l "`which python`"<div class="se-preview-section-delimiter"></div>#l: 代表软连接<div class="se-preview-section-delimiter"></div>#软连接自身是所有人可读可写,但具体的权限依赖于其链接的文件lrwxrwxrwx. 1 root root 7 3月 22 15:04 /usr/bin/python -> python2ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l "`which python2`"<div class="se-preview-section-delimiter"></div>#第二层链接lrwxrwxrwx. 1 root root 9 3月 22 15:04 /usr/bin/python2 -> python2.7<div class="se-preview-section-delimiter"></div>#链接的原始文件ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l "`which python2.7`"-rwxr-xr-x. 1 root root 7136 11月 6 2016 /usr/bin/python2.7<div class="se-preview-section-delimiter"></div>
文件属性rwx
中r
表示read
(数字表示为4)、w
表示write
(数字表示为2)、x
表示执行 (数字表示为1)。三个未一组,连续出现三次(如下面命令行中所示), 第一组表示文件的所有者拥有的权限,第二组为文件所有者所在的用户组所拥有的权限,组内所有成员都具有的权限,第三组为其它用户的权限。
chmod a+x file
: 表示给文件增加所有人(a)可执行权限 (+x)
chmod u+x file
: 表示给文件增加所有者(u,user,)可执行权限 (+x)
chmod g+x
, chmod o+X
: 表示给文件增加组内人或其它人可执行权限
chmod 755 file
: 表示拥有者有可读写执行权限,其它人有可读执行权限。(7=4+2+1
; 5=4+1
)
具体使用man chmod
查看其它参数使用。
<div class="se-preview-section-delimiter"></div># 新建个文件ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ cat <<END >run.sh> echo " I am a script created by ehbio." > END<div class="se-preview-section-delimiter"></div># 查看其权限值ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rw-rw-r-- 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div># 更改权限值ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ chmod 755 run.sh<div class="se-preview-section-delimiter"></div># 查看其权限值<div class="se-preview-section-delimiter"></div># 注意多了3个xct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rwxr-xr-x 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div># 去除其它用户的可执行权限ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ chmod o-x run.sh <div class="se-preview-section-delimiter"></div># 注意看少了个xct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rwxr-xr-- 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div># 去除同组的可执行权限ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ chmod g-x run.sh<div class="se-preview-section-delimiter"></div># 注意看又少了个xct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rwxr--r-- 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div># 去除所有人的可执行权限ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ chmod a-x run.shct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rw-r--r-- 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div># 给所有人增加可执行权限ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ chmod a+x run.shct@iZ8vb3e9jtel4m99ss6e7eZ:~$ ls -l run.sh -rwxr-xr-x 1 ct ct 39 6月 14 23:12 run.sh<div class="se-preview-section-delimiter"></div>
如果一个文件有了可执行权限,是不是就可以执行了,我们来检测下。
ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ run.sh-bash: run.sh: 未找到命令<div class="se-preview-section-delimiter"></div>
事实上并非如此,输入命令,回车后,提示命令未找打,这是为什么呢?
这就涉及到环境变量的概念,通俗的讲,环境变量就是告诉电脑 (实际是操作系统)几个目录。这几个目录下存储又可执行文件,如前面显示的/usr/bin
目录,大部分的系统命令都在这个目录下。
当我们输入命令mkdir
时,系统就会在环境变量所代表的几个目录从前都厚去查找,哪个里面有mkdir
文件,然后去执行mkdir
命令。
系统中环境变量的名字是PATH
,其内容可通过下面的命令显示 (根据操作系统不同和配置不同,略有差别,但格式是统一的,:
分割的一堆路径):
ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ echo $PATH/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin<div class="se-preview-section-delimiter"></div>
所以如果我们想让自己的命令能被系统找到,就需要把命令所在的目录加到环境变量里面,怎么操作呢?
加到环境变量的路径必须是全路径,全路径指以/
开头或已~
开头的路径。
<div class="se-preview-section-delimiter"></div># 加到环境变量的路径必须是全路径,全路径指以/开头或已~开头的路径<div class="se-preview-section-delimiter"></div># 注意第一个PATH不含$, 第二个PATH有$符号<div class="se-preview-section-delimiter"></div># 我们后面会讲什么时候用$, 什么时候不用$ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ export PATH=$PATH:/home/ctct@iZ8vb3e9jtel4m99ss6e7eZ:~$ echo $PATH/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ct<div class="se-preview-section-delimiter"></div>
这时,我们在执行那个命令试试,成功运行了。
ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ run.sh I am a script created by ehbio.<div class="se-preview-section-delimiter"></div>
所以在以后安装了新的软件,或者写了新的脚本后,都把软件的可执行程序和可执行的脚本所在的目录,加到环境变量里面就可以了。
但是,在命令行中执行export
,对环境变量所做的修改,只对当前终端有效,退出后就无效了。为了使得这一操作,长期有效,我们需要把这句话写入一个文件中,一个登陆服务器就会被自动读取的文件中。
对于普通用户,在远程登录终端时,家目录下的~/.bash_profile
(不是~/.bashrc
, 在本地登录时才会被读取)会自动被读取,所以我们需要把export
语句加入到这个文件中。
<div class="se-preview-section-delimiter"></div># 这是我的~/.bash_profile中的内容,主要是最好一行。可以连续的加入多个路径。if [ -f ~/.bashrc ]; then . ~/.bashrcfiif [ -f ~/.bash_aliases ]; then . ~/.bash_aliasesfiexport PATH=$PATH:/home/ct:/home/bin:/home/soft/bowtie2/bin<div class="se-preview-section-delimiter"></div>
前面提到,系统查找命令的顺序是从环境变量的第一个目录到最后一个目录,在第一次碰到查询的命令后,就调用执行。假如系统存在一个python
命令,我们自己又安装了一个python
(假如在/home/ct/anaconda/bin目录下),如果我们想执行自己的python
程序,就需要把/home/ct/anaconda/bin
写在$PATH
前面,如下
<div class="se-preview-section-delimiter"></div># 注意$PATH的顺序ct@iZ8vb3e9jtel4m99ss6e7eZ:~$ export PATH=/home/ct/anaconda/bin:$PATH<div class="se-preview-section-delimiter"></div>
至此,我们可以熟练使用环境变量来简化命令的输入过程了,因为如果没有环境变量,我们就得需要运行/home/ct/anaconda/bin/python
来运行python
命令了。
环境变量这块,自己多操作下,就会慢慢理解熟练了。
环境变量的补充
PATH
只是众多环境变量中的一个变量,用于存储可执行文件所在的目录,以便在用户输入命令时可以查询的到。尤其是自己写的脚本或安装的程序,系统不会知道它们在哪个路径下,需要我们去提供给系统这些新的路径,学名叫设置环境变量。
此外常用到的环境变量还有LD_LIBARY_PATH
: 指定动态链接库 (so文件)的位置,一般在安装软件出错时会用到;PYTHONPATH
: 指定Python的安装包的路径;PERL5LIB
: 指定perl的安装包的路径。
设置环境变量要注意2点:1. 设置新的环境变量时一般要包含原始的环境变量,不能覆盖;2. 注意自己的目录和系统环境变量的目录的顺序,想让哪个先被找到,就先放哪个。
文件内容操作 (二)
文件排序
seq
: 产生一系列的数字; man seq
查看其具体使用。我们这使用seq
产生下游分析所用到的输入文件。
<div class="se-preview-section-delimiter"></div># 产生从1到10的数,步长为1ct@ehbio:~$ seq 1 1012345678910<div class="se-preview-section-delimiter"></div># 产生从1到10的数,步长为1,用空格分割ct@ehbio:~$ seq -s ' ' 1 101 2 3 4 5 6 7 8 9 10<div class="se-preview-section-delimiter"></div># 产生从1到10的数,步长为2<div class="se-preview-section-delimiter"></div># 如果有3个数,中间的数为步长,最后一个始终为最大值ct@ehbio:~$ seq -s ' ' 1 2 101 3 5 7 9<div class="se-preview-section-delimiter"></div># 还记得前面提到的标准输入和标准输出吧<div class="se-preview-section-delimiter"></div># 后台回复 标准输入 查看ct@ehbio:~$ cat <(seq 0 3 17) <(seq 3 6 18) >testct@ehbio:~$ cat test 036912153915<div class="se-preview-section-delimiter"></div>
sort
: 排序,默认按字符编码排序。如果想按数字大小排序,需添加-n
参数。
<div class="se-preview-section-delimiter"></div># 可能不符合预期的排序,系统首先排0,然后排1, 3, 6, 9ct@ehbio:~$ sort test012151533699<div class="se-preview-section-delimiter"></div># 按数字大小排序ct@ehbio:~$ sort -n test033699121515<div class="se-preview-section-delimiter"></div>
sort -u
: 去除重复的行,等同于sort | uniq
。
ct@ehbio:~$ sort -nu test03691215<div class="se-preview-section-delimiter"></div>
sort file | uniq -d
: 获得重复的行。(d
=duplication
)
ct@ehbio:~$ sort -n test | uniq -d3915<div class="se-preview-section-delimiter"></div>
sort file | uniq -c
: 获得每行重复的次数。
<div class="se-preview-section-delimiter"></div># 第一列为每行出现的次数,第二列为原始的行ct@ehbio:~$ sort -n test | uniq -c 1 0 2 3 1 6 2 9 1 12 2 15<div class="se-preview-section-delimiter"></div># 换一个文件看的更清楚ct@ehbio:~$ cat <<END >test2> a> b> c> b> a> e> d> a> END<div class="se-preview-section-delimiter"></div># 第一列为每行出现的次数,第二列为原始的行ct@ehbio:~$ sort test2 | uniq -c3 a2 b1 c1 d1 e<div class="se-preview-section-delimiter"></div># 在执行uniq操作前,文件要先排序,不然结果很诡异ct@ehbio:~$ cat test2 | uniq -c1 a1 b1 c1 b1 a1 e1 d1 a<div class="se-preview-section-delimiter"></div>
整理下uniq -c
的结果,使得原始行在前,每行的计数在后。
awk
是一个强大的文本处理工具,其处理数据模式为按行处理。每次读入一行,进行操作。OFS
: 输出文件的列分隔符 (output file column separtor);FS
为输入文件的列分隔符 (默认为空白字符)。awk
中的列从第1到n列,分别记录为$1
, $2
… $n
。BEGIN
表示在文件读取前先设置基本参数;与之相对应的是END
,只文件读取完成之后进行操作。不以BEGIN
, END
开头的{}
就是文件读取、处理的部分。
<div class="se-preview-section-delimiter"></div># 管道符还记得吧,后台回复 管道 可查看<div class="se-preview-section-delimiter"></div># awk的操作就是镀金上一步的结果,去除多余的空白,然后调换2列ct@ehbio:~$ sort test2 | uniq -c | awk 'BEGIN{OFS="\t";}{print $2, $1}'a 3b 2c 1d 1e 1<div class="se-preview-section-delimiter"></div>
对两列文件,安照第二列进行排序, sort -k2,2n
。
<div class="se-preview-section-delimiter"></div># 第二列按数值大小排序ct@ehbio:~$ sort test2 | uniq -c | awk 'BEGIN{OFS="\t";}{print $2, $1}' | sort -k2, 2nc 1d 1e 1b 2a 3<div class="se-preview-section-delimiter"></div># 第二列按数值大小排序<div class="se-preview-section-delimiter"></div># 第二列相同的再按第一列的字母顺序的逆序排序 (-r)<div class="se-preview-section-delimiter"></div># 注意看前3行的顺序与上一步结果的差异ct@ehbio:~$ sort test2 | uniq -c | awk 'BEGIN{OFS="\t";}{print $2,$1}' | sort -k2,2n -k1,1re 1d 1c 1b 2a 3<div class="se-preview-section-delimiter"></div>
FASTA序列提取
生成单行序列FASTA文件,提取特定基因的序列,最简单的是使用grep
命令。
grep
在前面也提到过,以后还会经常提到,主要用途是匹配文件中的字符串,以此为基础,进行一系列的操作。如果会使用正则表达式,将会非常强大。正则表达式版本很多,几乎每种语言都有自己的规则,本文档不会展开,用到哪个提哪个。
<div class="se-preview-section-delimiter"></div># 生成单行序列FASTA文件ct@ehbio:~$ cat <<END >test.fasta> >SOX2> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> >POU5F1> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> >NANOG> CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT> ENDct@ehbio:~$ cat test.fasta >SOX2ACGAGGGACGCATCGGACGACTGCAGGACTGTC>POU5F1ACGAGGGACGCATCGGACGACTGCAGGACTGTC>NANOGCGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT<div class="se-preview-section-delimiter"></div># grep匹配含有SOX2的行<div class="se-preview-section-delimiter"></div># -A 1 表示输出的行中,包含匹配行的下一行 (A: after)ct@ehbio:~$ grep -A 1 'SOX2' test.fasta >SOX2ACGAGGGACGCATCGGACGACTGCAGGACTGTC<div class="se-preview-section-delimiter"></div># 也可以使用AWK<div class="se-preview-section-delimiter"></div># 先判断当前行是不是 > 开头,如果是,表示是序列名字行,替换掉大于号,取出名字。<div class="se-preview-section-delimiter"></div># sub 替换, sub(被替换的部分,要替换成的,待替换字符串)<div class="se-preview-section-delimiter"></div># 如果不以大于号开头,则为序列行,存储起来。<div class="se-preview-section-delimiter"></div># seq[name]: 相当于建一个字典,name为key,序列为值。然后就可以使用name调取序列。ct@ehbio:~$ awk 'BEGIN{OFS=FS="\t"}{if($0~/>/) {name=$0; sub(">", "", name);} else seq[name]=$0;}END{print ">SOX2"; print seq["SOX2"]}' test.fasta>SOX2ACGAGGGACGCATCGGACGACTGCAGGACTGTC<div class="se-preview-section-delimiter"></div>
多行FASTA序列提取要麻烦些,一个办法就是转成单行序列,用上面的方式处理。
sed
和tr
都为最常用的字符替换工具。
ct@ehbio:~$ cat <<END >test.fasta> >SOX2> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> ACGAGGGACGCATCGGACGACTGCAGGAC> >POU5F1> CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT> CGGAAGGTAGTCGTCAGTGCAGCGAGTCC> >NANOG> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> ACGAGGGACGCATCGGACGACTGCAGG> ACGAGGGACGCATCGGACGACTGCAGGACTGTC> ACGAGGGACGCATCGGACGACTGCAGGACTGT> END<div class="se-preview-section-delimiter"></div># 给>号开头的行的行尾加个TAB键,以便隔开名字和序列<div class="se-preview-section-delimiter"></div># TAB键不可见,直接看看不大<div class="se-preview-section-delimiter"></div># \(\)表示记录匹配的内容,\1则表示()中记录的匹配的内容<div class="se-preview-section-delimiter"></div># 后面我们专门讲sedct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta >SOX2 ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGAC>POU5F1 CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGTCGGAAGGTAGTCGTCAGTGCAGCGAGTCC>NANOG ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGT<div class="se-preview-section-delimiter"></div>#使用cat -A 可以显示文件中所有的符号<div class="se-preview-section-delimiter"></div># ^I 表示tab键<div class="se-preview-section-delimiter"></div># $表示行尾ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | cat -A>SOX2^I$ACGAGGGACGCATCGGACGACTGCAGGACTGTC$ACGAGGGACGCATCGGACGACTGCAGGACTGTC$ACGAGGGACGCATCGGACGACTGCAGGAC$>POU5F1^I$CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT$CGGAAGGTAGTCGTCAGTGCAGCGAGTCC$>NANOG^I$ACGAGGGACGCATCGGACGACTGCAGGACTGTC$ACGAGGGACGCATCGGACGACTGCAGG$ACGAGGGACGCATCGGACGACTGCAGGACTGTC$ACGAGGGACGCATCGGACGACTGCAGGACTGT$<div class="se-preview-section-delimiter"></div># 把所有的换行符替换为空格<div class="se-preview-section-delimiter"></div># tr这个命令,前面提到过,若想不起来 `man tr`查看<div class="se-preview-section-delimiter"></div># 主意第二个参数,引号内为空格。ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | tr '\n' ' '>SOX2 ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGAC >POU5F1 CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT CGGAAGGTAGTCGTCAGTGCAGCGAGTCC >NANOG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGT <div class="se-preview-section-delimiter"></div># 把最后一个空格替换为换行符ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | tr '\n' ' ' | sed -e 's/ $/\n/'>SOX2 ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGAC >POU5F1 CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT CGGAAGGTAGTCGTCAGTGCAGCGAGTCC >NANOG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGT<div class="se-preview-section-delimiter"></div># 把 ' >'替换为换行符 注意被替换的是 空格+大于号<div class="se-preview-section-delimiter"></div># 当连用多个替换命令时,使用-e 隔开ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | tr '\n' ' ' | sed -e 's/ $/\n/' -e 's/ >/\n>/g'>SOX2 ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGAC>POU5F1 CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGT CGGAAGGTAGTCGTCAGTGCAGCGAGTCC>NANOG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGG ACGAGGGACGCATCGGACGACTGCAGGACTGTC ACGAGGGACGCATCGGACGACTGCAGGACTGT<div class="se-preview-section-delimiter"></div># 把所有的空格替换掉ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | tr '\n' ' ' | sed -e 's/ $/\n/' -e 's/ >/\n>/g' -e 's/ //g'>SOX2 ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGAC>POU5F1 CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGTCGGAAGGTAGTCGTCAGTGCAGCGAGTCC>NANOG ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGT<div class="se-preview-section-delimiter"></div># 把TAB键转换为换行符ct@ehbio:~$ sed 's/^\(>.*\)/\1\t/' test.fasta | tr '\n' ' ' | sed -e 's/ $/\n/' -e 's/ >/\n>/g' -e 's/ //g' -e 's/\t/\n/g' >SOX2ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGAC>POU5F1CGGAAGGTAGTCGTCAGTGCAGCGAGTCCGTCGGAAGGTAGTCGTCAGTGCAGCGAGTCC>NANOGACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGT<div class="se-preview-section-delimiter"></div>
或者简单点,直接用前面的awk
略微做下修改。
<div class="se-preview-section-delimiter"></div># 差别只在一点<div class="se-preview-section-delimiter"></div># 对于单行fasta文件,只需要记录一行,seq[name]=$0<div class="se-preview-section-delimiter"></div># 对于多好fasta文件,需要把每一行序列都加到前面的序列上,seq[name]=seq[name]$0ct@ehbio:~$ awk 'BEGIN{OFS=FS="\t"}{if($0~/>/) {name=$0; sub(">", "", name);} else seq[name]=seq[name]$0;}END{print ">SOX2"; print seq["SOX2"]}' test.fasta>SOX2ACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGACTGTCACGAGGGACGCATCGGACGACTGCAGGAC<div class="se-preview-section-delimiter"></div>
命令运行监测
- 检测命令的运行时间
time command
ct@ehbio:~$ time sleep 5real 0m5.003s # 程序开始至结束的时间,包括其它进程占用的时间片和IO时间user 0m0.001s # 进程真正执行占用CPU的时间, sys 0m0.002s # 进程在内核中调用所消耗的CPU时间user+sys是进程实际的CPU时间。如果多线程执行,这个时间可能大于Real。如果IO是瓶颈,则real会大于user+sys (单线程)。<div class="se-preview-section-delimiter"></div>
查看正在运行的命令和其资源使用
top
- top输出界面第一行主要信息是负载显示,分别是1分钟、5分钟、15分钟前到现在的任务队列的平均长度。
- 一般与CPU数目相当为好,过大系统负载超额,反应慢。
- 在top输出界面输入
u
, 会提示输入用户名,以查看某个用户的进程。 - 重点关注的是%MEM列,查看系统占用的内存是否超出。
ct@ehbio:~$ top -a #按内存排序显示top - 09:02:11 up 224 days, 8:34, 30 users, load average: 40, 33, 28Tasks: 1561 total, 1 running, 1550 sleeping, 0 stopped, 10 zombieCpu(s): 0.6%us, 0.2%sy, 0.0%ni, 99.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%stMem: 2642768880k total, 2094619800k used, 548149080k free, 4310240k buffersSwap: 86472700k total, 73226016k used, 13246684k free, 193383748k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 32527 ct 20 0 2631m 1.7g 1332 S 0.0 0.7 100:34.87 rsem-run-em 29273 ct 20 0 4094m 692m 3396 S 0.0 0.3 45:18.83 java -Xmx1000m40148 mysql 20 0 21.9g 606m 6116 S 1.3 0.2 2536:06 /usr/sbin/mysqld31040 ct 20 0 1887m 77m 2604 S 0.3 0.0 180:43.16 [celeryd: <div class="se-preview-section-delimiter"></div>
- 查看系统进程
ps auwx | grep 'process_name'
文件系统和磁盘信息监测
查看系统硬盘大小和分配
ct@ehbio:~$ df -hFilesystem Size Used Avail Use% Mounted on/dev/sda3 193G 112G 71G 62% /tmpfs 127G 104K 127G 1% /dev/shm/dev/sda2 477M 102M 351M 23% /boot/dev/sda1 200M 264K 200M 1% /boot/efi/dev/mapper/ehbiobp1 137T 10T 127T 7% /ehbioB/dev/mapper/ehbiocp1 137T 32T 104.8T 23% /ehbioC/dev/mapper/ehbiodp1 137T 56T 81T 41% /ehbioD<div class="se-preview-section-delimiter"></div>
ct@ehbio:~$ du -sh *268M blog4.0K browserMimic.py5.6G CAFE386M chip73M class4.0K config.file4.0K do_not_del_r_test.Rmd7.2M ehbio20K ehbio_logo.png12K ehbio_weixin.jpg4.0K Grid_with_line.Rmd8.0K heatmap_nonlinear.pdf8.0K heatmap_nooutlier.pdf<div class="se-preview-section-delimiter"></div>
软件安装
不同于windows,Linux下软件安装的方式比较多样,有些也比较复杂。每种安装方式都有自己的优点和局限,也都有可能遇到问题。在我们理解了原理之后,借助谷歌,可以更好地帮助解决问题。
系统包管理器安装
软件安装最方便的、一般也不容易出问题的是利用系统自带的包管理工具,可以解决大部分的依赖问题。
<div class="se-preview-section-delimiter"></div># centos<div class="se-preview-section-delimiter"></div># 如果长时间没更新,先运行下updateyum update<div class="se-preview-section-delimiter"></div># 如果不知道软件具体名字,可以先用一个关键字search一下, 选择正式的名字<div class="se-preview-section-delimiter"></div># 需要注意的是一般的服务器都是64 bit,需要选x86_64版本yum search soft_name or soft_descriptionyum search soft_official_name<div class="se-preview-section-delimiter"></div>
但也有一些不足,主要3点:
- 需要根用户的权限。
- 如果系统版本老,安装的软件版本也会比较老。使用新版本有时又会发生冲突。
- 生物信息学中不少软件不在系统的安装源里面。
解决这些问题,就需要自己去软件官网查找最新的分法包,又有两种可能,一种是分法包直接就是编译好的软件,下载下来设置下可执行属性并放入环境变量就可以运行了,如于blast
或bowtie
这样的工具。
另一种则是需要从源码编译安装,下面主要讲解下这个。
源码编译安装
源码编译经典的三部曲configure
, make
, make install
。如果不出问题,对着执行下来就安装好了,也不一定知其所以然。但出了问题,就不是比较容易解决的。如果知道这背后的机制,还是会有帮助的。
configure
是检查系统的库文件、类文件、依赖软件是否存在以及它们的版本是否满族需求,并根据实际检测结果生成Makefile的工具。一般是一堆bash命令的组合。通常也需要在这一步配置一些参数。最常用的就是指定软件的安装目录--prefix=/home/ct/soft/specific_name
。make
则是具体的编译过程。编译的语句都写在了Makefile
中。make
默认编译Makefile中出现的第一个target
,也可以指定target
编译,并根据Makefile的设置方式依次编译所有依赖的东西。Makefile通常的格式和布局如下,有兴趣的可以自己去学,或者我们再出一个教程。
# 假设当前文件夹下Makefile文件中内容如下 ct@ehbio:~$ cat Makefile# first: target名字# echo "compile first": target对应的命令,任何Linux命令都可以first:echo "compile first"all: first secondecho "compile all"second:echo "compile second"# 直接运行make,会make第一个出现的targetct@ehbio:~$ makeecho "compile first"compile first# make first与直接make相同,因为它出现在第一个 ct@ehbio:~$ make firstecho "compile first"compile first# all依赖于first, second,因此make all会先执行make first, make second# 然后才是自己所代表的命令 ct@ehbio:~$ make allecho "compile first"compile firstecho "compile second"compile secondecho "compile all"compile all
有些软件的安装,在执行完make
后就获得了可执行程序,可以跳过make install
的过程,只需要放入环境变量就可以运行了。但部分软件还需要一些依赖关系,所以需要执行make install
才算完成了完整的安装。
make install
通常是拷贝make
编译出来的可执行文件或者依赖的库文件(如果有的话)到configure
时的--prefix
指定的目录下。安装好的软件放入环境变量, 就可以快乐的运行了。
两条注意:
从源码编译最难解决的问题就是依赖的库文件、头文件、其它软件的缺失或版本不匹配,没有统一的解决办法,原则就是
缺啥补啥
。三部曲每一步的执行,屏幕上都会输出比较多的信息,一定仔细看最后有没有
ERROR
类的字样,对判断软件有无安装成功和下一步要怎么做会很有帮助。
Linux包的安装的通用方式主要这些,后面还会提到两种虚拟安装方式,也都是为了简化安装而提出的。
Python包的安装
在没有Anaconda
(或其前身canopy)出现之前,Python包以其管理混乱、安装困难著称。有了Anaconda
后,不只python包的安装简单了,其它软件的安装也都方便了 (详见后面Anaconda的两个福利)。
- 首先下载Anaconda的安装包 https://www.continuum.io/downloads。
- Anaconda的安装包做的很人性化,一个bash脚本,只要运行
bash Anacond*x86_64.sh
,然后按照提示操作就可以了。 - 按照好后,设置或刷新下环境变量就可以使用了。
- 此后再安装python的包只需要执行
pip install pakcage_name
或conda install pakckage_name
就可以了。 - 这里唯一需要注意的就是确认使用的
python
或pip
确实是Anaconda安装的python
或pip
。which python
查看使用的python命令。- 如果使用的还是系统默认的python,则需要检查下环境变量的设置。
Anaconda的两个福利
- 头文件和库文件库
这是Anaconda安装后的目录结构
bin envs Examples imports lib LICENSE.txt pkgs share varconda-meta etc gcc include lib64 mkspecsplugins ssl<div class="se-preview-section-delimiter"></div>
其中lib目录下,一部分是依赖的动态链接库, .so
文件;这也是在源码编译时最常见的拦路虎。通常,只需要把这个目录放入环境变量LD_LIBRARY_PATH
里面比如export LD_LIBARY_PATH=${LD_LIBARY_PATH}:anaconda_path/lib
就可以解决问题。
cairo libitm.a libQtScript.so.4cmake libitm.la libQtScript.so.4.8engines libitm.so libQtScript.so.4.8.7gcc libitm.so.1 libQtScriptTools.lagcj-4.8.5-14 libitm.so.1.0.0 libQtScriptTools.prlglib-2.0 libitm.spec libQtScriptTools.solibargtable2.a libjpeg.a libQtScriptTools.so.4libargtable2.la libjpeg.la libQtScriptTools.so.4.8libargtable2.so libjpeg.so libQtScriptTools.so.4.8.7libargtable2.so.0 libjpeg.so.8 libQtSql.lalibargtable2.so.0.1.8 libjpeg.so.8.4.0 libQtSql.prllibasan.a libmkl_avx2.so libQtSql.solibasan.la libmkl_avx512_mic.so libQtSql.so.4libasan_preinit.o libmkl_avx512.so libQtSql.so.4.8libasan.so libmkl_avx.so libQtSql.so.4.8.7
- bioconda
bioconda提供了一个虚拟环境,方便软件的编译安装。具体的我没用过,可以读下 徐洲更的生信软件的好帮手-bioconda。
R包的安装
R包的安装具体看之前的R教程。
需要注意的也是依赖的软件或库文件的版本,同样的Anaconda提供的lib库也可以直接拿来用。
备注
文中凡是提到环境变量的地方都可链接到之前提到的环境变量使用的文章,请务必仔细读两遍。
如果软件版本或依赖实在解决不了的,用Docker,虚拟出一个新的系统来解决,具体见。
Original link
原文链接 http://blog.genesino.com//2017/06/bash1/
微信公众号
http://mp.weixin.qq.com/s/yKP1Kboji9N4p2Sl1Ovj0Q
- Linux的Bash学习
- linux bash学习
- linux bash shell 学习
- Linux Bash 学习
- Linux bash学习
- Linux Bash 学习笔记(1)
- Linux bash 部分命令学习
- linux 认识与学习 bash
- 认识和学习 Linux BASH
- Linux Bash Shell 学习笔记
- linux bash shell学习笔记
- linux BASH编程学习笔记
- Linux学习之Bash Shell
- 【Bash百宝箱】Linux shell学习
- Linux 认识与学习 bash
- Linux学习---bash及其特性
- Linux学习----bash脚本编程
- Linux---认识与学习BASH
- C++Primer Plus(第六版) 第十二章 第一题
- Javascript自定义错误,继承Error
- javascript的一道this综合题目
- css兼容总结
- PERL能为我做什么(1)
- Linux bash学习
- 浅谈http协议
- Android零基础入门第19节:Button使用详解
- HDU2112 最短路入门题 spfa
- jquery选择器效率问题
- 解决 Linux 下 Sublime Text 3中文输入
- cad快捷键命令大全 图文并茂
- E
- spring boot框架接受http请求并处理的代码公式