Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问 *** 作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
Shell 在线工具
Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。
由于习惯的原因,简洁起见,本文出现的 "shell编程" 都是指 shell 脚本编程,不是指开发 shell 自身。
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:
在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh ,它同样也可以改为 #!/bin/bash 。
#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
输入一些代码,第一行一般是这样:
#!/bin/bash
echo "Hello World !"
运行实例 »
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
echo 命令用于向窗口输出文本。
1、作为可执行程序
将上面的代码保存为 test.sh,并 cd 到相应目录:
注意,一定要写成 ./test.sh ,而不是 test.sh ,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
2、作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
Linux系�».shellå·¥å ·æå°è¾åº
shellèæ¬é½æ¯ä»¥#!/bin/bashå¼å¤´ï¼è¿æ¯åºå®çåæ³ï¼å ¶ä¸/bin/bashæ¯bashå½ä»¤çè·¯å¾ãé£ä¹Linuxç³»ç»shellå·¥å ·å¦ä½æå°è¾åºå¢ï¼è·æä¸èµ·æ¥ççå§ï¼
ä¸è¬é½ä¼éè¿chmodæäºshellèæ¬çå¯æ§è¡æéã
å¨shellèæ¬ä¸çæå°è¾åºé常ä¼æechoåprintf两ç§ï¼åè ä¼èªå¨æ¢è¡ã
å¨shellä¸å¦æç¨åå¼å·("")ä½ä¸ºæå°è¾åºçå 容æ¶ï¼å¦æåå¼å·ä¸æç¹æ®å符éè¦å¨ç¹æ®å符åå ä¸è½¬ä¹å符\,å½ç¶ä¹å¯ä»¥ä½¿ç¨åå¼å·æè ä¸ä½¿ç¨å¼å·ç´æ¥è¾åºï¼ä½¿ç¨åå¼å·æè ä¸ä½¿ç¨å°±ä¸éè¦ç¨å°è½¬ä¹å符ã
æ ¼å¼æ¿ä»£ç¬¦
æä¸äºå¸¸ç¨çæ ¼å¼æ¿ä»£ç¬¦ä¼ç»å¸¸å¨æå°è¾åºä¸è¢«ç¨å°,æ ¼å¼æ¿ä»£ç¬¦åªè½ç¨å¨printfè¾åºä¸ã
%-5s:表示5个å符宽度ï¼å ¶ä¸ç-表示左对é½
%-4.2f:å ¶ä¸çf表示浮ç¹åï¼4.2代表é¿åº¦ä¸º4个å符ä¸å°æ°ç¹2ä½ï¼å¦æå°æ°ç¹è¶ è¿2ä¼è¿è¡åèäºå ¥ï¼-表示左对é½ã
æ´å½¢ï¼
%d:æ´æ°çåæ°ä¼è¢«è½¬æä¸æ符å·çåè¿å¶æ°å
%u:æ´æ°çåæ°ä¼è¢«è½¬æä¸æ 符å·çåè¿å¶æ°å
%o:æ´æ°çåæ°ä¼è¢«è½¬æä¸æ 符å·çå «è¿å¶æ°å
%x:æ´æ°çåæ°ä¼è¢«è½¬æä¸æ 符å·çåå è¿å¶æ°å,并以å°åabcdef表示
%X:æ´æ°çåæ°ä¼è¢«è½¬æä¸æ 符å·çåå è¿å¶æ°å,并以大åABCDEF表示
æµ®ç¹åæ°ï¼
%fdoubleåçåæ°ä¼è¢«è½¬æåè¿å¶æ°å,é»è®¤åå°æ°ç¹ä»¥ä¸å ä½,åèäºå ¥
%edoubleåçåæ°ä»¥ææ°å½¢å¼æå°,æä¸ä¸ªæ°åä¼å¨å°æ°ç¹å,å ä½æ°åå¨å°æ°ç¹å,èå¨ææ°é¨åä¼ä»¥å°åçeæ¥è¡¨ç¤º.
%Eä¸%eä½ç¨ç¸å,å¯ä¸åºå«æ¯ææ°é¨åå°ä»¥å¤§åç'Eæ¥è¡¨ç¤º.
%gdoubleåçåæ°ä¼èªå¨éæ©ä»¥%fæ%eçæ ¼å¼æ¥æå°,å ¶æ åæ¯æ ¹æ®æ¬²æå°çæ°å¼åæ设置çææä½æ°æ¥å³å®.
%Gä¸%gä½ç¨ç¸å,å¯ä¸åºå«å¨ä»¥ææ°å½¢ææå°æ¶ä¼éæ©%Eæ ¼å¼.
å符åå符串ï¼
%c读å符串ç第ä¸ä¸ªå符
%sè¾åºæå®å®½åº¦çå符å 容.
%på¦ææ¯åæ°æ¯"void*"åæéå使ç¨åå è¿å¶æ ¼å¼æ¾ç¤º
æå°è¾åº
å¨åèæ¬çæ¶åæ´å¤çä¼ä½¿ç¨echoä½ä¸ºæå°è¾åºï¼ä¸ä¹ æ¯æ§çä¼ä½¿ç¨åå¼å·ã
echo
[root@localhosttmp]#echo"helloword"
helloword
printf
é»è®¤printfæ¯ä¸æ¢è¡ç
[root@localhosttmp]#printf"helloword"
helloword[root@localhosttmp]#
éè¦æ¢è¡å ä¸\nåæ°
[root@localhosttmp]#printf"helloword\n"
helloword
[root@localhosttmp]#
ç¼åshellèæ¬
vimscrip.sh
#!/bin/bash
printf"%-5s%-10s%-4s\n"NoNameMark
printf"%-5s%-10s%-4.2f\n"1aaa10.111
printf"%-5s%-10s%-4.2f\n"2bbb20.146
æäºèæ¬æ§è¡æéï¼chmodu+xscrip.sh
å¦æ使ç¨echoå°±ä¸è½ç¨æ ¼å¼æ¿ä»£ç¬¦
#!/bin/bash
echoNoNameMark
echo1aaa10.111
echo2bbb20.146
注æäºé¡¹
å¨echoï¼printfä¸ä½¿ç¨-e,-nåæ°æ¶ï¼-eï¼-nåºè¯¥åºç°å¨å½ä»¤è¡å ¶å®å符ä¹åã
-e:å¦æè¦å¨echoçåå¼å·ä½¿ç¨è½¬ä¹åºåä½ä¸ºåæ°å¾éè¦ä½¿ç¨-eåæ°
-n:忽ç¥æ«å°¾çæ¢è¡ç¬¦
ä¸ä½¿ç¨-eåæ°
[root@localhosttmp]#echo"1\n2"
1\n2
使ç¨-eåæ°
[root@localhosttmp]#echo-e"1\n2"
转ä¹åºåï¼
/n:æ¢è¡
/t:tabé®
彩è²è¾åº
åä½é¢è²å æ¬ï¼0=éç½®ï¼30=é»è²ï¼31=红è²ï¼32=绿è²ï¼33=é»è²ï¼34=èè²ï¼35=æ´çº¢ï¼36=éè²ï¼37=ç½è²
èæ¯é¢è²å æ¬ï¼0=éç½®ï¼40=é»è²ï¼41=红è²ï¼42=绿è²ï¼43=é»è²ï¼44=èè²ï¼45=æ´çº¢ï¼46=éè²ï¼47=ç½è²
echo-e"\e[132mhelloword\e[0m"
\e[132m:å°åä½é¢è²è®¾ä¸ºç»¿è²ï¼\e[0m:å°é¢è²éç½®
sed 命令从文本或者标准输入中每次读入一行数据。
我们先从简单的实例出发,看下该命令怎么将一列中的 chrm12 , chrom2 等转换成 chr12 , chr2 的格式。
虽然示例文件处理仅仅只有三行,但我们可以将这种处理方式运用到上G甚至更大的数据文件中,而不用打开整个文件进行处理。并且,可以借助重导向实现对数据处理结果的输出。
sed 替换命令采用的格式是
sed 会自动搜索符合 pattern 的字符串,然后修改为 replacement (我们想要修改后的样子)。一般默认 sed 只替换第一个匹配的 pattern ,我们可以通过添加全局标识 g 将其应用到数据的所有行中。
如果我们想要忽略匹配的大小写,使用 i 标识
默认 sed 命令支持基本的POSIX正则表达式(BRE),可以通过 -E 选项进行拓展(ERE)。很多的Linux命令都这种方式,像常用的 grep 命令。
再看一个实例,如果我们想把 chr1:28647389-28659480 这样格式的文字转换为三列,可以使用:
我们聚焦在第二个命令 sed 上。初看杂乱无章,但是从最大的结构看依旧是
先看 pattern 部分,这是由几个简单正则表达式组成的复合体,几个 () 括起来的字符串可以单独看。第一个匹配 chr 加上一个非冒号的字符,第二个和第三个都是匹配多个数字。最开始的 ^ 表示以 chr 起始(前面没有字符),各个括号中间的是对应的字符。整体的 pattern 的目的就是为了找到文本中符合这种模式的字符串,如果只是想把这个模式找出来的话,几个括号可以不用加。显然这几个括号的作用就是将它们划分成多个域,帮助 sed 进行处理。可以看到 replacement 部分存在 \1 , \2 , \3 ,它恰好对应 () 的顺序。这样我们在中间插入 \t 制表符,就可以完成我们想要的功能:将原字符串转换为三列。
我本身对字符串并不是非常熟悉,懂一些元字符,可能讲解的不是很到位。不熟悉正则表达式的朋友,可以学习和参考下 学习正则表达式 ,是我从Github上Copy到的非常好的学习资料,有兴趣也可以Fork学习。
上山的路总是有很多条,我们下面看下其他实现该功能的办法:
这三种方式看起来都非常简单有效。它处理字符串的思路不是从匹配pattern然后替换入手,不对,应该说是不是从匹配所有pattern然后替换入手。处理的关键是只处理字符串中看似无用的连字符 : 与 - ,将其替换成制表符从而轻松完成分割。
sed 's/:/\t/' | sed 's/-/\t/' 可以通过 -e 选项写为 sed -e 's/:/\t/' -e 's/-/\t/' ,效果等价。
默认 sed 命令支持基本的POSIX正则表达式(BRE),可以通过 -E 选项进行拓展(ERE)。很多的Linux命令都这种方式,像常用的 grep 命令。
再看一个实例,如果我们想把 chr1:28647389-28659480 这样格式的文字转换为三列,可以使用:
我们聚焦在第二个命令 sed 上。初看杂乱无章,但是从最大的结构看依旧是
先看 pattern 部分,这是由几个简单正则表达式组成的复合体,几个 () 括起来的字符串可以单独看。第一个匹配 chr 加上一个非冒号的字符,第二个和第三个都是匹配多个数字。最开始的 ^ 表示以 chr 起始(前面没有字符),各个括号中间的是对应的字符。整体的 pattern 的目的就是为了找到文本中符合这种模式的字符串,如果只是想把这个模式找出来的话,几个括号可以不用加。显然这几个括号的作用就是将它们划分成多个域,帮助 sed 进行处理。可以看到 replacement 部分存在 \1 , \2 , \3 ,它恰好对应 () 的顺序。这样我们在中间插入 \t 制表符,就可以完成我们想要的功能:将原字符串转换为三列。
我本身对字符串并不是非常熟悉,懂一些元字符,可能讲解的不是很到位。不熟悉正则表达式的朋友,可以学习和参考下 学习正则表达式 ,是我从Github上Copy到的非常好的学习资料,有兴趣也可以Fork学习。
上山的路总是有很多条,我们下面看下其他实现该功能的办法:
这三种方式看起来都非常简单有效。它处理字符串的思路不是从匹配pattern然后替换入手,不对,应该说是不是从匹配所有pattern然后替换入手。处理的关键是只处理字符串中看似无用的连字符 : 与 - ,将其替换成制表符从而轻松完成分割。
sed 's/:/\t/' | sed 's/-/\t/' 可以通过 -e 选项写为 sed -e 's/:/\t/' -e 's/-/\t/' ,效果等价。
默认, sed 会输出每一行的结果,用 replacement 替换 pattern ,但实际中我们可能会因此得到不想要的结果。比如下面的这个例子。
如果我们想要抓出 gtf 文件第九列的转录名,可能会使用以下命令
我们可以发现一些没有转录名行的结果是输出整行,这可不是我们想要的。一种解决办法是在使用 sed 之前先抓出有 transcript_id 的行。其实 sed 命令本身也可以通过选项和参数设定解决这个问题,这里我们可以用 -n 选项关闭 sed 输出所有行,在最末的 / 后加 p 只输出匹配项。
注意方括号内 ^ 是非(取反)的意思。
解释如下:
+ 号的使用是一种非贪婪的方法。很多新手会用 * ,这是贪婪 *** 作,往往会得不偿失,需要注意喔。
使用 * 时它会尽量多地去匹配符合要求的模式。
我们也可以用 sed 命令来获取特定范围的行,比如说我要取出头10行,可以使用
20到50行
当然 sed 的功能特性远远不止这些,有待于大家更多地挖掘。不过需要注意的是,尽量让工具干它最擅长的事情。如果是复杂地大规模计算,还是最好写个Python脚本。
首先需要记住 连续 命令和 管道 命令的区别:前者是简单地一个一个按顺序运行程序(一般用 &&或者 );后者前一个程序的输出结果会直接传到下一个命令程序的输入中(这不就是流程化 *** 作么,用 | 分隔)。
子shell可以让我们在一个独立的shell进程中执行连续命令。
首先看个例子
发现仅仅加了个括号,结果就不同了。第二个命令就用了子shell,它把两个 echo 命令放进单独的空间执行后将结果传给下游。
子shell在对 gtf 文件进行 *** 作时有个非常有意思有用的用处。我们如果想对 gtf 文件排序,但是又想要保留文件头部注释信息,我们就能够用两次 grep *** 作分别抓出注释和非注释信息,然后又把它结合在一起。下面看看效果,用 less 进行检查:
可以看到,子shell确实能够给我们提供非常有用的 *** 作去组合命令实现想要的功能。
很多生信命令行工具需要提供多个输入和输出参数,这用在管道命令里可能会导致非常低效的情形(管道只接受一个标准输入和输出)。幸好,我们可以使用命令管道来解决此类问题。
命名管道 ,也成为FIFO(先入先出,额,这不是队列么:smile:)。它是一个特殊的排序文件,命名管道有点像文件,它可以永久保留在你的文件系统上(估计本质就是文件吧~)。
我们用 mkfifo 来生成它
可以它看它权限的第一个字符是p,指代是pipe。说明是个特殊文件。
我们像文件一样对它进行一些 *** 作
比如当使用一个生信命令行工具
in1.fq in2.fq 就可以上游输出数据到 processing_tool 的命名管道;同理 out1.fq out2.fq 可以是命名管道用来写进输出数据。
但这样我们每次都得不停地创建和删除这些文件,解决办法是使用匿名管道,也叫进程替换。
不能光说,看看例子就知道和理解了。
echo 命令运行后使用了进程替换,产生匿名文件,然后匿名文件被重导向 cat 命令。
把它用到工具上,就变成了(假定上游zcat下游执行grep命令)
关于Linux数据处理工具内容全部整理发布在我的博客上。 详情点击
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)