参考文章:
鸟哥的Linux私房菜基础学习篇
1.shell script介绍
shell script 是利用 shell 的功能所写的一个“程序 (program)”,这个程序是使用纯文本文件,将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正则表达式、管线命令与数据流重导向等功能,以达到我们所想要的处理目的。
简单的说, shell script 就像是早期 DOS 年代的批处理文件 (.bat),最简单的功能就是将许多指令汇整写在一起, 让使用者很轻易的就能够 one touch 的方法去处理复杂的动作 (执行一个文件 “shell script” ,就能够一次执行多个指令)。 而且 shell script 更提供阵列、循环、条件与逻辑判断等重要功能,让使用者也可以直接以 shell 来撰写程序,而不必使用类似 C 程序语言等传统程序撰写的语法呢!
shell script 可以简单的被看成是批处理文件, 也可以被说成是一个程序语言,且这个程序语言由于都是利用 shell 与相关工具指令, 所以不需要编译即可执行,且拥有不错的除错 (debug) 工具。
2. shell脚本在编写过程中的注意事项
- 命令是从上而下、从左而右地分析与执行;
- 命令的执行中,命令、选项与参数间的多个空格都会被会忽略掉;
- 空白行也会忽略掉,[Tab]键所产生的空白同样视为空格键;
- 如果读取到Enter符号,开始执行该行(或该串)命令;
- 如果一行的内容太多,则可以使用【[Enter]】来扩展至下一行;
- 【#】可作为注释,任何加在#后面的数据将全部被视为注释文字而被忽略。
3. 鸟哥推荐的shell脚本格式
[dmtsai@study ~]$ mkdir bin; cd bin
[dmtsai@study bin]$ vim hello.sh
#!/bin/bash
# Program:
# This program shows "Hello World!" in your screen.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello World! \a \n"
exit 0
在本章当中,请将所有撰写的 script 放置到你主文件夹的 ~/bin 这个目录内,未来比较好管理啦!上面的写法当中,鸟哥主要将整个程序的撰写分成数段,大致是这样:
- 第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称: 因为我们使用的是 bash ,所以,必须要以“
#!/bin/bash ”来宣告这个文件内的语法使用 bash 的语法!那么当这个程序被执行时,他就能够载入 bash 的相关环境配置文件 (一般来说就是 non-login shell 的 ~/.bashrc), 并且执行 bash 来使我们下面的指令能够执行!这很重要的!(在很多状况中,如果没有设置好这一行,那么该程序很可能会无法执行,因为系统可能无法判断该程序需要使用什么 shell 来执行啊!) - 程序内容的说明: 整个 script 当中,除了第一行的“ #! ”是用来宣告 shell 的之外,其他的 # 都是“注解”用途!
所以上面的程序当中,第二行以下就是用来说明整个程序的基本数据。一般来说, 建议你一定要养成说明该 script 的:1. 内容与功能;2. 版本信息; 3. 作者与联络方式; 4. 创建日期;5. 历史纪录 等等。这将有助于未来程序的改写与 debug 呢! - 主要环境变量的宣告: 建议务必要将一些重要的环境变量设置好,鸟哥个人认为, PATH 与 LANG (如果有使用到输出相关的信息时)是当中最重要的! 如此一来,则可让我们这支程序在进行时,可以直接下达一些外部指令,而不必写绝对路径呢!比较方便啦!
- 主要程序部分:就将主要的程序写好即可!在这个例子当中,就是 echo 那一行啦!
- 执行成果告知 (定义回传值) 是否记得我们在第十章里面要讨论一个指令的执行成功与否,可以使用 $? 这个变量来观察~ 那么我们也可以利用 exit 这个指令来让程序中断,并且回传一个数值给系统。 在我们这个例子当中,鸟哥使用 exit 0 ,这代表离开 script 并且回传一个 0 给系统, 所以我执行完这个 script 后,若接着下达 echo $? 则可得到 0 的值喔! 更聪明的读者应该也知道了,呵呵!利用这个exit n (n 是数字) 的功能,我们还可以自订错误讯息, 让这支程序变得更加的 smart 呢!
除了记录这些信息之外,在较为特殊的程序码部分,个人建议务必要加上注解说明,可以帮助你非常非常多! 此外,程序码的撰写最好使用巢状方式,在包覆的内部程序码最好能以 [tab] 按键的空格向后推, 这样你的程序码会显的非常的漂亮与有条理!在查阅与 debug 上较为轻松愉快喔! 另外,使用撰写 script 的工具最好使用 vim 而不是 vi ,因为 vim 会有额外的语法检验机制,能够在第一阶段撰写时就发现语法方面的问题喔!
4. 生信分析中常用的shell脚本
1. for…do…done (固定循环)
for 这种语法,是“ 已经知道要进行几次循环”的状态!他的语法是:
for var in con1 con2 con3 ...
do
程序段
done
以上面的例子来说,这个 $var 的变量内容在循环工作时:
第一次循环时, $var 的内容为 con1 ;
第二次循环时, $var 的内容为 con2 ;
第三次循环时, $var 的内容为 con3 ;
....
我们可以做个简单的练习。假设我有三种动物,分别是 dog, cat, elephant 三种, 我想每一行都输出这样:“There are dogs…”之类的字样,则可以:
[dmtsai@study bin]$ vim show_animal.sh
#!/bin/bash
# Program:
# Using for .... loop to print 3 animals
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#对变量${i}利用 for ${i} in A B C D 的方式遍历指定。
for animal in dog cat elephant
do
echo "There are ${animal}s.... "
done
#对变量${i}利用 for ${i} $(seq 1 100)的方式连续指定。
for number in $(seq 1 100) # seq 为 sequence(连续) 的缩写之意
do
echo "There are ${number}.... "
done
2. for…do…done 的数值处理
除了上述的方法之外,for 循环还有另外一种写法!语法如下:
for (( 初始值; 限制值; 执行步阶 ))
do
程序段
done
这种语法适合于数值方式的运算当中,在 for 后面的括号内的三串内容意义为:
初始值:某个变量在循环当中的起始值,直接以类似 i=1 设置好;
限制值:当变量的值在这个限制值的范围内,就继续进行循环。例如 i<=100;
执行步阶:每作一次循环时,变量的变化量。例如 i=i+1。
值得注意的是,在“执行步阶”的设置上,如果每次增加 1 ,则可以使用类似“i++”的方式,亦即是 i 每次循环都会增加一的意思。好,我们以这种方式来进行 1 累加到使用者输入的循环吧!
[dmtsai@study bin]$ vim cal_1_100-2.sh
#!/bin/bash
# Program:
# Try do calculate 1+2+....+${your_input}
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a number, I will count for 1+2+...+your_input: " nu
s=0
for (( i=1; i<=${nu}; i=i+1 ))
do
s=$((${s}+${i}))
done
echo "The result of '1+2+3+...+${nu}' is ==> ${s}"
一样也是很简单吧!利用这个 for 则可以直接限制循环要进行几次呢!
5. script 的执行方式差异 (bash, sh script, source)
- 不同的 script 执行方式会造成不一样的结果喔!尤其影响 bash 的环境很大呢! 利用bash、sh来执行脚本:在子程序中执行,“当子程序完成后,在子程序内的各项变量或动作将会结束而不会传回到父程序中”!
- 利用 source来执行脚本:在父程序中执行, source 对 script 的执行方式可以使各项动作都会在原本的 bash内生效!这也是为啥你不登出系统而要让某些写入 ~/.bashrc 的设置生效时,需要使用“ source ~/.bashrc ”而不能使用“ bash ~/.bashrc ”是一样的啊!
6. shell script 的追踪与 debug
scripts 在执行之前,最怕的就是出现语法错误的问题了!那么我们如何 debug 呢?有没有办法不需要通过直接执行该 scripts 就可以来判断是否有问题呢?呵呵!当然是有的!我们就直接以 bash 的相关参数来进行判断吧!
[dmtsai@study ~]$ sh [-nvx] scripts.sh
选项与参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
范例一:测试 dir_perm.sh 有无语法的问题?
[dmtsai@study ~]$ sh -n dir_perm.sh
# 若语法没有问题,则不会显示任何信息!
范例二:将 show_animal.sh 的执行过程全部列出来~
[dmtsai@study ~]$ sh -x show_animal.sh
+ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin
+ export PATH
+ for animal in dog cat elephant
+ echo 'There are dogs.... '
There are dogs....
+ for animal in dog cat elephant
+ echo 'There are cats.... '
There are cats....
+ for animal in dog cat elephant
+ echo 'There are elephants.... '
There are elephants....
请注意,上面范例二中执行的结果并不会有颜色的显示!鸟哥为了方便说明所以在 + 号之后的数据都加上颜色了! 在输出的讯息中,在加号后面的数据其实都是指令串,由于 sh -x 的方式来将指令执行过程也显示出来, 如此使用者可以判断程序码执行到哪一段时会出现相关的信息!这个功能非常的棒!通过显示完整的指令串, 你就能够依据输出的错误信息来订正你的脚本了!
熟悉 sh 的用法,将可以使你在管理 Linux 的过程中得心应手!至于在 Shell scripts 的学习方法上面,需要“多看、多模仿、并加以修改成自己的样式!” 是最快的学习手段了!
转载:https://blog.csdn.net/xiaomotong123/article/details/106540266