脚本干货分享

01

start

开始


写法一:

#!/bin/bash

#!位于解释器路径之前,

/bin/bash是Bash的解释器命令路径。

写法二:

#!/bin/bash -ex

-e,类似于在第二行写set -e其意义是Exit immediately if a command exits with a non-zero status.

-x 的意思是Print commands and their arguments as they are executed



02

frontend printing

终端打印

$ name=dou; echo -e "my name is\t$name"
my name is      dou

如果需要在不同的命令之间输出一些信息给用户进行提示,在编写脚本时,输出不一样的颜色或者背景会比较醒目。



打印彩色字体 echo -e "\e[1;32m This is green text \e[0m"

打印彩色背景 echo -e "\e[1;42m This is green text \e[0m"


printf

举例:

$ printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456
1     Sarath     80.35
%s、%c、%d和%f都是格式替换符,%-5s的含义是左对齐且宽度为5,%-4.2f\n 的含义是浮点数且宽度为5保留两位小数。



03

variable

变量


添加环境变量

例如:

PATH="$PATH:/home/user/bin"
export PATH
#### 或者
export PATH=/opt/myapp/bin:$PATH
export LD_LIBRARY_PATH=/opt/myapp/lib;$LD_LIBRARY_PATH
如果只是在当前shell 执行,可以写一个函数放在bashrc
addpath() { [ -d "$2" ] && eval $1=\"$2\$\{$1:+':'\$$1\}\" && export $1 ; }

使用addpath PATH /add/path 可以快速把一个路径添加到当前shell中



04

Mathematical operations

数学运算

#!/bin/bash
no1=4;
no2=5;
let result=no1+no2
echo $result
#自加
let no1++
let no+=6
# []
result=$[ no1 + no2 ]


bc

no=54;
result=`
echo "$no * 1.5" | bc`
echo $result

$ echo "scale=4;3/8" | bc
.3750

echo "sqrt(100)" | bc #Square root

echo "10^10" | bc #Square



05

File descriptor and redirection

文件描述符及重定

当一个命令发生错误并退回时,它会返回一个非0的退出状态;而当命令成功完成后,它会返回数字0。退出状态可以从特殊变量$?中获得(在命令执行之后立刻运行echo $?,就可以打印出退出状态)

分别重定向输出和错误可以使用cmd 2>stderr.txt 1>stdout.txt;重定向到一个文件可以使用cmd 2>&1 output.txt

不查看输出内容或者错误,可以重定向到“垃圾桶”/dev/null 中。

tee可以在显示输出的时候,将输出内容重定向到一个文件,但是需要注意的是,错误信息是不会保存到重定向的文件中的,tee只能接受stdout。如果像追加操作而非覆盖的话,需要使用tee -a参数。


将脚本内部的文本块进行重定向

有时候需要在脚本中输出大量内容,可以使用cat<<EOF>>

#!/bin/bash
cat<<EOF>log.txt
LOG FILE HEADER
This is a
test log file
Function: System statistics
EOF
# 两个EOF之间的内容会写进log.txt
# 如果不指定文件,会直接打印到屏幕



06

array

数组

  • 定义数组array_var=(1 2 3 4 5 6)

  • 调用某个数组元素echo ${array_var[0]}

  • 调用所有元素 echo ${array_var[*]}

  • 调用数组长度 echo ${ #array_var[*]}

  • 调用数组索引 echo ${!sample_names[*]}




07

get ,set date and delay

获取、设置日期和延时

用格式串结合 + 作为date命令的参数,可以按照你的选择打印出对应格式的日期

$ date "+%d %B %Y"
21 October 2017

检查命令花费的时间,可以把开始和结束时间嵌入写好的脚本头和尾

#!/bin/bash
start=$(date +%s)

commands;
statements;

end=$(date +%s)
difference=$(
echo "scale=2;($end-$start)/60" | bc)
echo Time taken to execute scripts is $difference mins

脚本中生成延时
使用sleep函数,sleep 1m延迟1分钟



08

Shell script debugging

shell 脚本调试

shell的调试相对简单和单调。可以使用set -x和set +x对脚本进行部分调试。

对于想要输出的命令的区域,可以限定在set -x和set +x之前



09

Functions and parameters

函数与参数

定义函数:

# 定义函数
function fname()
{
    statements;
}

# 使用函数
fname arg1 arg2

例如

fname()
{
   
echo $1, $2; #访问参数1和参数2
    echo "$@";#以列表的方式一次性打印所有参数
    echo "$*"; #类似于$@,但是参数被作为单个实体
    return 0; #返回值
}



10

Exit state

退出状态

查看命令是否成功执行,如果成功退出则推出状态为0。

#!/bin/bash
fastqc input.bam
if [ $? -eq 0 ];
then
    echo "fastqc executed successfully"
else
    echo "fastqc terminated unsuccessfully"
fi



11

Output variable input

输出变输入

使用管道(pipe)连接每个过滤器 cmd1|cmd2|cmd3

字shell 和反引用

# 子shell
ouptup=$(commands)
# 反引用
output=`commands`



12

Read keyboard input

读取键盘输入

在用户不知道脚本怎么用的前提下,可以提示用户在直接运行脚本后进行参数的输入。

在shell中,可以使用read 直接读取键盘输入。

# 让用户输入内容
read -p "input fastq file name: " inputfile
fastqc
$inputfile

read -p "are you sure to continue(y/n): " judge
if [ "$judge" == "y" ]
then
    echo ok coutine
else
    exit 0
fi



13

Repeat command until successful

重复命令直到成功

有些命令比如(下载),可能需要重复执行指导成功,可以使用whil来构造函数进行判断

repeat() { while :; do $@ && return; sleep 30; done }

# : 是shll内建命令每次会返回退出码0
# $@ 表示输入的所有命令和参数

### 增加延时尝试
waitrepeat() { while :; do $@ && return; sleep 30s; done }



14

Field separator and iterator

字段分隔符和迭代器

IFS shell 中内置的字段分隔符,IFS的默认值为:空白(包括:空格,tab, 和新行),当文件中的分隔符是逗号或者其他,就需要使用到IFS

oldIFS=$IFS
IFS=,
for item in $data;
do
    echo Item: $item
done
IFS=$oldIFS

使用循环进行迭代

# for
for var in list
do
    commands #使用变量$var
done

for((i=0;i<10;i++))
{
    commands;
#使用变量$i
}

# while
while condition
do
    commands;
done

# until 直到条件为真时执行
x=0;
until [
$x -eq 9 ];
do
    let x++; echo $x;
done



15

Comparative test

比较测试

可以用if、if else以及逻辑运算符进行测试,用比较运算符来比较数据项。除此之外,还有一个test命令也可以用于测试。


if判断



# if条件
if condition;
then
    commands;
fi

# else if和else
if condition;
then
    commands;
else if condition; then
    commands;
else
    commands;
fi

算数比较
条件通常被放置在封闭的中括号内,且一定要注意在[或]与操作数之间有一个空格。
[ $var -eq 0 ] #当 $var 等于 0 时,返回真
[ $var -ne 0 ] #当 $var 为非 0 时,返回真
# 其他
-gt:大于
-lt:小于
-ge:大于等于
-le:小于等于

文件系统
[ -f $file_var ]:如果给定的变量包含正常的文件路径或文件名,则返回真。
[ -x
$var ]:如果给定的变量包含的文件可执行,则返回真。
[ -d
$var ]:如果给定的变量包含的是目录,则返回真。
[ -e
$var ]:如果给定的变量包含的文件存在,则返回真。
[ -c
$var ]:如果给定的变量包含的是一个字符设备文件的路径,则返回真。
[ -b
$var ]:如果给定的变量包含的是一个块设备文件的路径,则返回真。
[ -w
$var ]:如果给定的变量包含的文件可写,则返回真。
[ -r
$var ]:如果给定的变量包含的文件可读,则返回真。
[ -L
$var ]:如果给定的变量包含的是一个符号链接,则返回真。

字符串
使用字符串比较时,最好使用双中括号。
[[ $str1 == $str2 ]]:当str1等于str2时,返回真。
[[
$str1 != $str2 ]]:如果str1和str2不相同,则返回真
[[ -z
$str1 ]]:如果str1包含的是空字符串,则返回真。
[[ -n
$str1 ]]:如果str1包含的是非空字符串,则返回真。

逻辑运算符
&& 逻辑与 || 逻辑或
if [[ -n $str1 ]] && [[ -z $str2 ]] ;
then
    commands;
fi


test

如果不想写括号,可以使用test

if test $var -eq 0 ;
then
    commands;
fi
分享