【树】Linux笔记-3 shell脚本编程

【树】Linux笔记-3 shell脚本编程

以下内容是参与【生信技能树-全球听第7期】的课程笔记,记录人:小瑛 ,有问题可在公众号后台留言

小白小白,请注意:笔记中出现的所有文件路径,仅作为参考,请勿模仿!

1. Linux 系统环境

文件系统结构:一切皆文件

/       # 虚拟目录的根目录。通常不会在这里存储文件
/bin    # 二进制目录,存放许多用户级的GNU工具
/boot   # 启动目录,存放启动文件
/dev    # 设备目录, Linux在这里创建设备节点
/etc    # 系统配置文件目录
/home   #  主目录,Linux在这里创建用户目录
/lib    # 库目录,存放系统和应用程序的库文件
/media  # 媒体目录,可移动媒体设备的常用挂载点
/root   # root用户的主目录
/sbin   # 系统二进制目录,存放许多GNU管理员级工具
/run    # 运行目录,存放系统运作时的运行时数据
/tmp    # 临时目录,可以在该目录中创建和删除临时工作文件
/usr    # 用户二进制目录,大量用户级的GNU工具和数据文件都存储在这里

Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。

  • 内核 是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
  • shell 是系统的用户界面,提供了用户与内核进行交互操作的一种接口。shell也是一门编程语言(脚本编程)

常用命令

lscpu               # 查看CPU信息
free -h             # 查看内存信息
df -h               # 查看硬盘信息
du -h -d 1          # 查看文件大小,显示一层
top                 # 查看系统进程
ps -ef              # 查看系统进程
ps -ef | grep 用户名 # 用于查找该用户提交的进程

2. 变量

调用变量时,要在变量前面加$符号

● 环境变量

​ 用于存储有关shell会话和工作环境的系统变量

● 位置参数变量

​ 用于用于向命令或程序脚本中传递信息

$n   # n为数字,$0代表命令本身,$1一$9代表第1一9个参数,10以上的参数需要用大括号包含,如${10}
$*   # 这个变量代表命令行中所有的参数,把所有的参数看成一个整体
$@   # 这个变量也代表即令行中所有的参数,不过$@把每个参数区别对待
$#   # 这个变量代表命令行中所有参数的个数

● 状态变量

​ 用于记录命令的运行结果

$?   # 获取执行上一个指令的执行状态返回值,返回0表示成功,非0则表示失败
$$   # 获取当前执行的shell脚本的进程号PID
$!   # 获取上一个后台工作的进程的进程号PID
$_   # 获取在此之前执行的命令或脚本的最后一个参数

● 自定义变量

​ 由用户自行定义的变量,可用于用户编写的脚本,多个命令间的值传递等

a=gene       # 赋值的时候=左右不要空格,否则会报错
echo $a
echo 'This is a $a'   # 单引号里面的变量$a不会被解释
echo "This is a $a"   # 双引号里面的变量$a会被解释,从颜色也可以看出来

● 关于括号

shell编程默认$后面的内容为变量,如果后面还要接其他命令,调用变量的时候需要加{},防止和其他命令粘连,让系统把其他命令也误认为是变量。

shell中的括号(小括号,中括号,大括号) linux中的(),(()),[],[[]],{}的作用 - 雅思敏 - 博客园
https://www.cnblogs.com/yasmi/articles/5129571.html

3. 结构化语句

● 条件语句 if

之前遇到的 awk 里面的 if 和这里的 if 在语法和使用上不一样。

命令格式

# 形式 1
if command  # 条件
then
    commands
fi
_________________________
# 形式 2
if command  # 条件
then
    commands
else
    commands
fi
_________________________
# 形式 3
if command1      # 条件1
then
    commands
else
    if command2  # 条件2
    then
        commands
    fi
fi

常见的条件(中括号两边的空格一定要留)

# 1.数值判断 
[ INT1 -eq INT2 ]   # INT1 和 INT2 两数相等返回为真     =
[ INT1 -ne INT2 ]   # INT1 和 INT2 两数不等返回为真     ≠
[ INT1 -gt INT2 ]   # INT1 大于 INT2 返回为真          >
[ INT1 -ge INT2 ]   # INT1 大于等于 INT2 返回为真       ≥
[ INT1 -lt INT2 ]   # INT1 小于 INT2 返回为真          <
[ INT1 -le INT2 ]   # INT1 小于等于 INT2 返回为真       ≤
_______________________________________________________________________
# 2.字符判断
[ -z STRING ]             # 如果STRING的长度为零则返回为真,即空是真
[ -n STRING ]             # 如果STRING的长度非零则返回为真,即非空是真
[ STRING1 ]               # 如果字符串不为空则返回为真,与-n类似
[ STRING1 === STRING2 ]   # 如果两个字符串相同则返回为真
[ STRING1 != STRING2 ]    # 如果字符串不相同则返回为真
[ STRING1 < STRING2 ]     # 如果STRING1字典排序在STRING2前面则返回真,>同理
_______________________________________________________________________
# 3.文件判断
[ -a FILE ]    # 如果FILE存在则为真
[ -d FILE ]    # 如果FILE存在且是一个目录则返回为真
[ -f FILE ]    # 如果FILE存在且是一个普通文件则返回为真

● 循环语句 for / while

for 循环语句的常见格式

# 一般格式
for i in list 
do 
    commands
done

# 示例
for i in 1 2 3 4 5      # 1 2 3 4 5 可以表示为{1..5}
do
echo ${i} "Hello Word!" # 这下面还可以写其他命令
done
# 单行形式
for i in {1..5};do echo ${i} "Hello Word!";done 
# 输出
1 Hello Word!
2 Hello Word!
3 Hello Word!
4 Hello Word!
5 Hello Word!

# 如果list的内容很杂,可以将内容赋值给一个变量
list="CDS exon gene start_codon stop_codon transcript UTR"
for i in ${list}
do
echo "This is ${i}"
done

# 利用反引号来合并代码
ls file*              # 列出当前路径下file开头的文件,接下来需要对这些文件批量操作
for i in `ls file*`   # 把上一行命令写入反引号内会被优先执行
do
mv ${i} ${i}.txt      # 批量重命名加上.txt后缀,此处可以先用echo替代mv,看到效果后再用mv
done

while 循环语句的常见格式

# 格式 1 
while read id
do
    commands
done

# 格式 2 (不推荐)
while rcommand
do
    other commands
done

# 格式 1 示例
ls file*
ls file* | while read x  #  x是自己定义的变量名, while read 是按行读取
do
mv ${x} ${x}.txt
done
# 以下的代码方便理解while read 是按行读取
cat test.txt | while read x
do
echo ${x}  # 直接打印测试文件test.txt中的内容
sleep 2s   # 每执行一次echo ${x}都睡2s
done
# 输出以下内容,每行显示之间间隔2s
1 Hello Word!
2 Hello Word!
3 Hello Word!
4 Hello Word!
5 Hello Word!

● 参数扩展

掐头去尾

${变量#关键字}   # 若变量内容从头开始的数据符合"关键字”,则将符合的最短数据删除
${变量##关键字}  # 若--------头-------------------,----------长------
${变量%关键字}   # 若--------尾-------------------,----------短------
${变量%%关键字}  # 若--------尾-------------------,----------长------

替换(去中间)

${变量/旧字符串/新字符串}   # 若变量内容符合"旧字符串”,则首个旧字符串会被新字符串替换。
${变量//旧字符串/新字符串}  # --------------------,-全部---------------------。

# “去中间”的示例
# 创建 10 个文件 test_file_1 ~ test_file_10 ,使用循环语句(建议用 while read id),将上面的 test_file_1 ~ test_file_10 进行重命名,如:test_file_1 改为 test_1
touch test_file_{1..10} 
ls test_file_* | while read x
do
mv ${x} ${x/_file/}  # 把_file替换为空,起到删除的效果
done

切片(取索引)

索引下标从0开始,R是从1开始。

${变量:索引}       # 截取变量从索引位置到末尾的所有字符
${变量:索引:n}     # ---------------开始的n个字符
${变量:索引:(-n)}  # ---------------到倒数第n+1位的所有字符
${变量:索引:-n}    # 同上

# 示例
id=Data.tar.gz
echo ${#id}        # 显示字符长度:11
echo ${id:3}       # 显示索引3,也就是第4位开始到最后
echo ${id:3:5}     # 显示索引3,也就是第4位开始的5个字符
echo ${id:3:(-1)}  # 显示索引3,也就是第4位开始到倒数第 1+1=2 个字符
echo ${id:3:-1}    # 同上

4. shell脚本编程

● Vim 编辑器

是从vi发展出来的文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。本质上和Rstudio、pycharm一样都是代码编辑器

工作模式

工作模式图.png

一般流程:vim 文件名 → i → 键入内容 → ESC → :wq

vim编写的内容如果符合某一种编程语言的语法,就可以用对应的语言去解释,文件名后缀也尽量体现文本格式

  • bash 文件.sh shell 语言
  • Python 文件.py Python 语言
  • R 文件.r R 语言

键盘图

键盘图.png

查看帮助文档

vimtutor zh_CN     # 查看中文帮助文档
                   # 该文档属于vim的工作模式,任何操作要符合vim语法规则

● shell脚本

编写shell脚本的规范

  1. 文件名以.sh结尾
  2. 脚本首行:#!/bin/bash ,#! 是Linux的Shebang 符号,指定解释器,/bin/是bash所在的文件夹
  3. 脚本的正文

输出文件

bash test.sh 1>1.log 2>2.log     # 如果test.sh文件的输出很多,直接输出到屏幕会刷屏
                                 # 将结果保存到日志文件中
                                 # 1:标准输出流     正确输出 保存到 1.log中
                                 # 2:标准误输出流   错误输出 保存到 2.log中
bash test.sh 1>output.log 2>&1   # 不管正确错误,结果文件都存放到output.log中

修改文件权限

chmod 764 test.sh    # 修改文件的权限为:自己全可以,同组可读可写,别人可读
                     # 执行后文件会变成绿色
~/test.sh            # 修改权限之后就可以用路径调用

参数传递

cat test.sh
# 显示内容如下
#!/bin/bash
cat $1     # test.sh内的命令正文,查看第一个文件内容 $1 位置参数

# 运行这个脚本
bash test.sh 需要执行的文件1   # $1 对应 需要执行的文件1 

● 任务提交

nohup 需要运行的命令 &     # 挂载操作的格式
# 返回值
[1] 11169                # 数字是任务号
nohup: ignoring input and appending output to 'nohup.out'  # 所有输出都保存到 nohup.out

# 查看后台处理进程
top      # 实时显示系统中各个进程的资源占用状况,按q退出
ps -ef   # Process Status 列出当前系统中运行的进程列表

# 返回值
[1]+ Done     # 成功
[1]+ Exit     # 失败

# 终止任务
kill PID      # PID是ps -ef后的第一个数字,不是任务号

往期回顾
Linux笔记-1 https://www.jianshu.com/p/78aad4b705af
Linux笔记-2 软件安装 https://www.jianshu.com/p/403fa1322155

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353