Shell 是什么
其实在之前的文章里有略微提到过。生信分析中不可或缺的一个伙伴,不管你主打R还是Python,Shell是必修课。当然,Shell的指令相对而言比较简单,不需要太多的学习成本,看完本文大概可以解决90%的日常问题了。
Shell的特点及用途
- 和unix指令一样,输入指令然后执行就好
- 指定什么时候按照什么条件用什么指令进行命令执行
- 指定输入文件和输出文件
基本设置
首先用随便什么IDE创建一个最简单的Shell脚本文件,没有IDE的话可以新建一个txt文件,文件名后缀改成sh就好,比方说这里创建了一个text.sh。
#!/bin/sh
echo "Hello, world!"
- 在写正式的code之前需要写一行
#!/bin/sh
,这个相当于告诉系统Shell要来了。单独使用bash
的时候,需要写#!/bin/bash
。 - 用以下的方法可以执行这个shell脚本文件
$ sh test.sh
or
$ bash test.sh
这样就可以获得运行结果"Hello, world!"
。
输入&输出
echo
输出、 read
输入
把刚才的test.sh
改一下,
#!/bin/sh
read NAME
echo "Hello, $NAME!"
执行一下,输入自己的名字Jason,就会得到这样的结果。当然要输入名字哈,要不然机器会一直等着你。
$ sh test.sh
Jason
Hello, Jason!
bash的话改成如下就好了。挂上一个-e
FLAG。
#!/bin/bash
echo -e "Hello\n$NAME!"
变量
- 变量名可以是英文字母,数字和下划线。
a~z
,A~Z
,0~9
,_
。 - 用
=
给变量赋值。前后不要有空格。文字用双引号""
。 - 要引用变量的话,在变量前加上
$
。或者$
加上{}
。 - 一个变量里只能保存一个值。
- 用
readonly
来防止变量被覆盖。 - 用
unset
可以删除变量。
#!/bin/sh
var="这是变量"
VaR_2="这也是变量"
echo "Var_2=$VaR_2"
VaR_2="VaR_2被改变了。"
echo ${VaR_2}
readonly var
var="用readonly尝试改变变量。"
执行以后得到以下结果
jason$ sh test.sh
Var_2=这也是变量
VaR_2被改变了。
test.sh: line 11: var: readonly variable
特殊变量
变量 | 意思 |
---|---|
$0 | 脚本名 |
$1 ~ $9 | 参数,第一个参数是$1 ,第二个参数是$2 |
$# | 脚本里所有的参数数量 |
$* | 所有参数集中在一起处理 |
$@ | 所有的参数个别处理 |
$? | 当前命令是否成功执行,成功1,失败0 |
$$ | 当前的脚本的Process ID |
$! | 当前在背后执行的Process ID |
https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337
#!/bin/sh
echo "\$0(脚本名): $0"
echo "\$1(第一个参数): $1"
echo "\$2(第二个参数): $2"
echo "\$3(第二个参数): $3"
echo "\$#(参数的数量): $#"
echo "\"\$*\": \"$*\""
echo "\"\$@\": \"$@\""
VAR="exit的值应该是0"
echo $?
当执行test.sh
脚本并在后面添加first
, second
,third
三个参数以后,就会得到以下的结果
jason$ sh test.sh first second third
$0(脚本名): test.sh
$1(第一个参数): first
$2(第二个参数): second
$3(第二个参数): third
$#(参数的数量): 3
"$*": "first second third"
"$@": "first second third"
0
特殊文字
* ? [ ' " ` \ $ ; & ( ) | ~ < > # % =
这些都是特殊字符。想要把这些当作普通字符来使用的时候得在前面加上\
。
序列(Bash)
bash shell可以仿照下面的格式写。
#!/bin/bash
ARRAY=(item1 item2 item3 item4)
ARRAY[0]="ITEM1"
ARRAY[2]="ITEM3"
echo "ARRAY[0]: ${ARRAY[0]}"
echo "ARRAY[1]: ${ARRAY[1]}"
echo "ARRAY[*]: ${ARRAY[*]}"
echo "ARRAY[@]: ${ARRAY[@]}"
得到以下的结果
sh test.sh
ARRAY[0]: ITEM1
ARRAY[1]: item2
ARRAY[*]: ITEM1 item2 ITEM3 item4
ARRAY[@]: ITEM1 item2 ITEM3 item4
操作
shell可以进行四则运算和逻辑计算
符号 | 意思 | 例子 |
---|---|---|
+ | 加法 | echo expr 10 + 20 => 30 |
- | 减法 | echo expr 20 - 10 => 10 |
* | 乗 | echo expr 11 \* 11 => 121 |
/ | 除 | echo expr 10 / 2 => 5 |
% | 余数 | echo expr 10 % 4 => 2 |
= | 指定 | a=$b |
== | 等于 | [ "$a" == "$b" ],a和b一样的话会返回TRUE |
!= | 不等于 | [ "$a" != "$b" ] ,a和b不一样的话会返回TRUE |
比较 | 意思 |
---|---|
-eq | 是否等于 |
-ne | 是否不等于 |
-gt | 是否大于 |
-lt | 是否小于 |
-ge | 是否大于等于 |
-le | 是否小于等于 |
! | 不是 |
-o | 或者 |
-a | 并且 |
If 条件
用上面操作里的语法写一段包含语法的shell脚本。
#!/bin/sh
if [ "$1" -gt "$2" ]
then
echo "参数1比参数2大"
elif [ "$1" -eq "$2" ]
then
echo "参数1和参数2一样"
else
echo "参数1比参数2小"
fi
自己随便指定参数执行一下test.sh
% sh test.sh 2 7
参数1比参数2小
% sh test.sh 10 10
参数1和参数2一样
% sh test.sh 10 9
参数1比参数2大
Switch条件
switch
的基本语法就是,case 参数 in 条件·值 )指令;; esac
- 如果条件·值符合参数,就会执行指令
#!/bin/sh
DRINK="coffee"
case "$DRINK" in
"beer") echo "啤酒"
;;
"juice") echo "果汁"
;;
"coffee") echo "咖啡"
;;
esac
执行一下
% sh test.sh
咖啡
Loop
break
中断continue
跳过
while循环
在符合条件的情况下执行
#!/bin/sh
a=0
while [ $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
% sh test.sh
0
1
2
3
4
until循环
和while
相反,执行直到合符条件
#!/bin/sh
a=0
until [ ! $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
% sh test.sh
0
1
2
3
4
for 循环
- for循环的基本格式是
for 变量 in 多个数值或者范围 do 指令 done
#!/bin/sh
for var in 0 1 2 3 4 #指定范围(Bash的话) => {0..4}
do
echo $var
done
sh test.sh
0
1
2
3
4
函数
#!/bin/sh
#指定函数
MyFunction () {
echo "函数的echo输出。"
}
MyParamFunc() {
echo "变量1:$1 变量2:$2"
}
#呼出函数
MyFunction
MyParamFunc param1 param2
% sh test.sh
函数的echo输出。
变量1:param1 变量2:param2
写在最后
本文里基本上覆盖了最常用到的shell脚本语法了。其实不只是需要做生信分析的科研人员,SE等职业码农也会经常用到这些内容。在unix里和其他脚本语言一起使用的话可以极大提高生产力。觉得有点帮助的话点个赞吧。