Linux-Shell 编程技巧学习-1

Introduction

主要记录关于 shell 编程的一些技巧性编写方式

Getting Started

注意: 可以考虑通过终端命令生成所需要运行的脚本,之后再运行脚本实现想要的功能,这样也方便检查命令运行的准确性。

注意: Linux 下的管道符相当于另开一个子进程来运行管道符后面的命令,退出管道符之后,管道符内的变量便不存在了;如 while read 下的管道符使用。

1. 变量的字符串替换

1
2
3
4
5
shell_path=/bak/data8/fass1/project_1123/shell
panel=${shell_path#*fass1}
## 输出结果:/project_1123/shell
panel=${panel///shell/} ## 这里的 // 意思是将匹配到的所有 shell/ 删除;若只有 / 则只对匹配到的第一个字符进行操作
## 输出结果:/project_1123

2. 判断读入的参数个数

通过识别传入脚本的参数个数来判断脚本是否被正确执行

1
2
3
4
5
#!/bin/bash
if [ $# != 1 ];then
echo -e "USAGE: $ sh $0 month"
exit 1;
fi

shell 脚本从外读取参数时,如何获取参数的相关信息,如个数,是否执行成功等

1
2
3
4
$0 --- 当前执行shell脚本的程序名
$# --- 一共传入的参数个数
$* --- 所有位置变量的值;即表示所有变量
$? --- 判断上一条命令是否执行成功,0 为成功;非0 为失败

3. 指定脚本执行之后,输出内容的存放路径

一般情况下,shell 脚本被执行之后,输出内容直接打印在终端,这样不方便后期查看 log 信息;故,我们可以考虑将脚本运行之后的打印信息输出到指定文件中

1
2
3
logfile=./log/log.txt
exec >> $logfile 2>&1
## 在脚本的开头加上 exec 命令,则会将脚本打印内容自动输出至给定的 log 文件

4. if 语句的判断方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
## 字符串比较
## = / != / -n / -z / str1
= ## 字符串相等的情况下为真
!= ## 不等为真
-n ## 字符串非空为真
-z ## 空字符串为真
if [[ $str1 ]]; then... ## 当直接给一个字符串时,当给定的字符串非空为真

## 数字比较
## -eq / -ne / -gt / -ge / -lt / -le
-eq ## 相等
-ne ## 不等
-gt ## 大于
-ge ## 大于等于
-lt ## 小于
-le ## 小于等于

## 文件比较
## -r / -w / -x / -f / -d / -c / -b / -s / -t
-r ## 可读 为真
-w ## 可写 为真
-x ## 可执行 为真
-f ## 文件存在 为真
-d ## 目录存在 为真
-c ## 文件字符特殊文件 为真
-b ## 文件为块特殊文件 为真
-s ## 文件大小非 0 为真
-t ## 当文件描述符(默认为 1 )指定的设备为终端时 为真

## 复杂逻辑判断
## -a / -o / !
-a or && ## 与
-o or || ## 或
! ## 非

5. for 循环的并行操作

在原有的基础上加上 & 符号, 实现并行效果

但是问题来了,要是需要循环的次数太多,那就会同时运行很多任务,这难免占用大量运算资源,所以我们可以考虑控制每个并行任务的执行次数,这样可以减少并行负担

1
2
3
4
5
for sample in {aa,dd,cc}; do
{
./xxx $sample;
}&
done

==注意== {} 内的代码是执行并行的部分,外面也可以有其他不用并行的语句

6. awk 单引号内引用外置变量

只能单引号内套双引号带正常的变量名引用。

1
2
message="hello world"
awk -F'\t' '{print "'"$message"'"}' aaa.txt

7. Linux 下的计划任务执行

通过 atcrontab 等命令可以实现在规定时间、规定周期内执行一定的指定任务…

1
2
3
4
$ crontab -e ## 进入编辑模式
*/10 * * * * [cmd...] ## 表示每隔10min执行一次[cmd...]
## 分钟[0-59] 小时[0-23] 日期[1-31] 月份[1-12] 星期[0-7](其中0/7均表示星期天)
25 3 * * 1,5 [cmd...] ## 表示每周1和周5的3:25分执行[cmd]


1
2
3
4
5
## 寻找满足条件的 bcl 路径
## find /data5/Rawdata/Sequencer/bcl/* -maxdepth 0 -type d -ctime -7 -cmin -30
## find /data5/Rawdata/Sequencer/bcl/* -maxdepth 0 -type d -ctime -7 -exec grep -c "{}" bcl_names.txt \;
## find -exec 嵌入管道符
##find /data5/Rawdata/Sequencer/bcl/* -maxdepth 0 -type d -ctime -7 -exec sh -c "echo {} \| awk '{print $0}'" \; -print