一、bash 基础
1.变量累加
| name=${name}yes |
| echo $a$b |
2.上个执行指令的回传值 echo $?
| [dmtsai@study ~] |
| /bin/bash |
| [dmtsai@study ~] |
| 0 < |
| [dmtsai@study ~] |
| bash: 12name=VBird: command not found... |
| [dmtsai@study ~] |
| 127 |
| |
| *使用?判断变量值 |
| [root@localhost ddd] |
| [root@localhost ddd] |
| [root@localhost ddd] |
| string1 |
| [root@localhost ddd] |
| [root@localhost ddd] |
| -bash: str: 无此变量 |
| |
| |
3.键盘读取read
| [dmtsai@study ~] |
| 选项与参数: |
| -p :后面可以接提示字符! |
| -t :后面可以接等待的“秒数!”这个比较有趣~不会一直等待使用者啦! |
| -s :隐藏键盘输入 |
| |
| [root@localhost ~] |
| input contents |

4.declare / typeset
| * declare/typeset |
| [dmtsai@study ~] |
| 选项与参数: |
| -a :将后面名为 variable 的变量定义成为阵列 (array) 类型 |
| -i :将后面名为 variable 的变量定义成为整数数字 (integer) 类型 |
| -x :用法与 export 一样,就是将后面的 variable 变成环境变量; |
| -r :将变量设置成为 readonly 类型,该变量不可被更改内容,也不能 unset |
| 范例一:让变量 sum 进行 100+300+50 的加总结果 |
| [dmtsai@study ~] |
| [dmtsai@study ~] |
| 100+300+50 以文本打印 |
| [dmtsai@study ~] |
| [dmtsai@study ~] |
| 450 |
5.与文件系统及程序的限制关系: ulimit
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -H :hard limit ,严格的设置,必定不能超过这个设置的数值; |
| -S :soft limit ,警告的设置,可以超过这个设置值,但是若超过则有警告讯息。 |
| 在设置上,通常 soft 会比 hard 小,举例来说,soft 可设置为 80 而 hard |
| 设置为 100,那么你可以使用到 90 (因为没有超过 100),但介于 80~100 之间时, |
| 系统会有警告讯息通知你! |
| -a :后面不接任何选项与参数,可列出所有的限制额度; |
| -c :当某些程序发生错误时,系统可能会将该程序在内存中的信息写成文件(除错用), |
| 这种文件就被称为核心文件(core file)。此为限制每个核心文件的最大容量。 |
| -f :此 shell 可以创建的最大文件大小(一般可能设置为 2GB)单位为 KBytes |
| -d :程序可使用的最大断裂内存(segment)容量; |
| -l :可用于锁定 (lock) 的内存量 |
| -t :可使用的最大 CPU 时间 (单位为秒) |
| -u :单一使用者可以使用的最大程序(process)数量。 |
6.自定义命名 alias/unalias
7.history/HISTSIZE
history如何显示时间、IP等信息
| [root@localhost a5_dtx] |
| [root@localhost a5_dtx] |
| 5 |
| [root@localhost a5_dtx] |
| 700 echo ${HISTSIZE} |
| 701 history |
| 702 HISTSIZE=5 |
| 703 echo ${HISTSIZE} |
| 704 history |
8.关于进程被挂起
9.万用字符(wildcard)与特殊符号


10.命令执行的判断依据: ; , &&, ||
| * cmd1;cmd2 不判断直接执行 |
| * cmd1&&cmd2 指令1正确($?=0)的情况下执行指令2;批量执行脚本神器 超级方便 |
| * cmd1||cmd2 指令1正确则不执行指令2,指令1不正确则执行指令2 |
| ls /etc/profile111 && echo "exist" || echo "not exist" && touch /etc/profile111 |
11.统计行数、字符等:wc
| [dmtsai@study ~] |
| 选项与参数: |
| -l :仅列出行; |
| -w :仅列出多少字(英文单字); |
| -m :多少字符; |
| |
| [root@localhost ddd] |
| process mysql not exist |
| |
| [root@localhost ddd] |
| 0 |
| process mysql exist |
12.快捷键补充
| * ctrl+r:搜索历史输入命令 避免history的低效率 |
| * ctrl+u/k:向前/后 删除指令串 |
| * ctrl+a/e:代替home/end键,到指令串的最前或者最后 |
| * ctrl+s/q:冻结/解冻前端 |
13.cut指令
| [dmtsai@study ~] |
| [dmtsai@study ~] |
| 选项与参数: |
| -d :后面接分隔字符。与 -f 一起使用; |
| -f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思; |
| -c :以字符 (characters) 的单位取出固定字符区间; |
| |
| [root@localhost ddd] |
| 1:2:3:4:5:6:a:b:c:d:e:f |
| [root@localhost ddd] |
| 2:3 |
| [root@localhost ddd] |
| :2:3 |
14.字符转换命令: tr, col, join, paste, expand
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -d :删除讯息当中的 SET1 这个字串; |
| -s :取代掉重复的字符! |
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -x :将 tab 键转换成对等的空白键 |
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -t :join 默认以空白字符分隔数据,并且比对“第一个字段”的数据, |
| 如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个! |
| -i :忽略大小写的差异; |
| -1 :这个是数字的 1 ,代表“第一个文件要用那个字段来分析”的意思; |
| -2 :代表“第二个文件要用那个字段来分析”的意思。 |
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -d :后面可以接分隔字符。默认是以 [tab] 来分隔的! |
| - :如果 file 部分写成 - ,表示来自 standard input 的数据的意思。 |
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空白键取代。 |
| 我们也可以自行定义一个 [tab] 按键代表多少个字符呢! |
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -b :后面可接欲分区成的文件大小,可加单位,例如 b, k, m 等; |
| -l :以行数来进行分区。 |
| PREFIX :代表前置字符的意思,可作为分区文件的前导文字。 |
15.管线命令(pipe)
| 那么如果这群数据必需要经过几道手续之后才能得到我们所想要的格式,应该如何来设置? |
| 这就牵涉到管线命令的问题了 (pipe) ,管线命令使用的是“ | ”这个界定符号! |
| 其实这个管线命令“ | ”仅能处理经由前面一个指令传来的正确信息,也就是 standard output 的信息,对于 stdandard error 并没有直接处理的能力。那么整体的管线命令可以使用下图表示 |

16.参数代换: xargs
| |
| [dmtsai@study ~] |
| 选项与参数: |
| -0 :如果输入的 stdin 含有特殊字符,例如 `, \, 空白键等等字符时,这个 -0 参数 |
| 可以将他还原成一般字符。这个参数可以用于特殊状态喔! |
| -e :这个是 EOF (end of file) 的意思。后面可以接一个字串,当 xargs 分析到这个字串时, |
| 就会停止继续工作! |
| -p :在执行每个指令的 argument 时,都会询问使用者的意思; |
| -n :后面接次数,每次 command 指令执行时,要使用几个参数的意思。 |
| 当 xargs 后面没有接任何的指令时,默认是以 echo 来进行输出喔! |
| ps -ef | grep java | grep -v "grep" | awk '{print $2}' | xargs kill |
17.关于减号的用途:-
18.数据流重导向
(1)指令执行过程的数据传输情况

(2)standard output 与 standard error output
| 标准输出指的是“指令执行所回传的正确的讯息”,而标准错误输出可理解为“指令执行失败后,所回传的错误讯息”;用数据重导向可以将standard output (简称 stdout) 与 standard error output (简称 stderr)分别传送到其他的文件或设备 |
| 1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ; |
| 2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ; |
| 3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ; |
| |
| ll / > ~/rootfile 将根目录下的目录写进rootfile这个文件;或者用1> |
| |
| 1> :以覆盖的方法将“正确的数据”输出到指定的文件或设备上; |
| 1>>:以累加的方法将“正确的数据”输出到指定的文件或设备上; |
| 2> :以覆盖的方法将“错误的数据”输出到指定的文件或设备上; |
| 2>>:以累加的方法将“错误的数据”输出到指定的文件或设备上; |
| |
| find /home -name .bashrc > list_right 2> list_error |
(3)/dev/null设备和特殊写法
| |
| find /home -name .bashrc 2> /dev/null |
| |
| |
| find /home -name .bashrc >list 2>list |
| find /home -name .bashrc >list 2>&1 |
| find /home -name .bashrc >list |
| |
| |
| 将原本由键盘输入的数据,改由文件内容来取代 |
| |
| |
| cat > catfile |
| |
| |
| cat > catfile < ~/.bashrc |
| |
| |
| cat > catfile << "eof" |
| |
| |
| cat >> aa.msg << EOF |
| test.line1 |
| test.line2 #向aa.msg文件夹输入以上两个文本;>>追加 >覆盖 |
| EOF |
二、正则表达式(Regular Expression)与文件格式化处理
揭开正则表达式的神秘面纱
正则表达式30分钟入门教程
正则在线校验1 正则在线校验2(多使用这两个网址练习)
1.grep的一些进阶
| -c 统计关键字次数;也可以用|wc -l代替 |
| -v 排除相关行 |
| -w 只显示全字符合的列 |
| -i 忽略字符大小写的差别 |
| -o 只输出文件中匹配到的部分 |
| -n 显示列号 |
| --color 关键字显示颜色;实际grep已经用alias设置为‘grep --color=auto’ |
2.正则相关
| * 利用[]搜索集合字符 |
| * 利用''搜寻特定字符 |
| |
| grep -n '[^a-z]oo' regular_express.txt |
| * 行首与行尾字符 ^ $ |
| ^ -1.表示否定 |
| [^a]表示“匹配除了a的任意字符”。 |
| [^a-zA-Z0-9]表示“找到一个非字母也非数字的字符”。 |
| [\^abc]表示“找到一个插入符或者a或者b或者c”。用[/abc]也Ok 但是需避免转义字符? |
| -2.表示限定开头 |
| /[(^\s+)(\s+$)]/g |
| (^cat)$ |
| (^cat$) |
| ^(cat)$ |
| ^(cat$) |
| |
| |
| * 任意一个字符. 与重复字符*(!!!和万用字符的含义不一样) |
| |
| |
| |
| |
| |
| * 限定连续 RE 字符范围 {} |
| -1.若为 {n} 则是连续n个的前一个RE字符 |
| -2.若是 {n,} 则是连续n个以上的前一个RE字符 |
| |
| |
| |
3.sed工具
| [dmtsai@study ~]$ sed [-nefr] [动作] |
| 选项与参数: |
| -n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到屏幕上。但如果加上 -n 参数后,则只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。 |
| -e :直接在命令行界面上进行 sed 的动作编辑; |
| -f :直接将 sed 的动作写在一个文件内, -f filename 则可以执行 filename 内的 sed 动作; |
| -r :sed 的动作支持的是延伸型正则表达式的语法。(默认是基础正则表达式语法) |
| -i :直接修改读取的文件内容,而不是由屏幕输出。 |
| 动作说明: [n1[,n2]]function |
| n1,n2 :不见得会存在,一般代表“选择进行动作的行数”,举例来说,如果我的动作是需要在 10 到 20 行之间进行的,则“ 10,20[动作行为] ” |
| function 有下面这些咚咚: |
| a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ |
| c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! |
| d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚; |
| i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); |
| p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ |
| s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正则表达式 |
| |
| * 以行为单位的新增/删除功能 |
| |
| [root@localhost ddd] |
| 1 root:x:0:0:root:/root:/bin/bash |
| 6 sync:x:5:0:sync:/sbin:/bin/sync |
| |
| [root@localhost ddd] |
| 1 root:x:0:0:root:/root:/bin/bash |
| 2 bin:x:1:1:bin:/bin:/sbin/nologin |
| drink tea |
| 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin |
| |
| [root@localhost ddd] |
| 1 root:x:0:0:root:/root:/bin/bash |
| 2 bin:x:1:1:bin:/bin:/sbin/nologin |
| line1 |
| line2 |
| |
| * 以行为单位的取代与显示功能 |
| |
| [root@localhost ddd] |
| 1 root:x:0:0:root:/root:/bin/bash |
| No line2 number |
| |
| [root@localhost ddd] |
| 2 bin:x:1:1:bin:/bin:/sbin/nologin |
| 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin |
| |
| * 部分数据的搜索并取代的功能 |
| |
| |
| |
| |
| |
| |
| |
4.延伸正则表达式
| |
| -1.grep -v '^$' regular_express.txt | grep -v '^#' ==管线命令 |
| -2.egrep -v '^$|^#' regular_express.txt ==延伸型的正则表达式;egrep也可以使用grep -E替代 |

5.文件的格式化与相关处理
不需要重新以vim去编辑,通过数据流重导向配合下面介绍的printf功能,以及awk指令
5.1格式化打印:printf
| [dmtsai@study ~]$ printf '打印格式' 实际内容 |
| 选项与参数: |
| 关于格式方面的几个特殊样式: |
| \a 警告声音输出 |
| \b 倒退键(backspace) |
| \f 清除屏幕 (form feed) |
| \n 输出新的一行 |
| \r 亦即 Enter 按键 |
| \t 水平的 [tab] 按键 |
| \v 垂直的 [tab] 按键 |
| \xNN NN 为两位数的数字,可以转换数字成为字符。 |
| 关于 C 程序语言内,常见的变量格式 |
| %ns 那个 n 是数字, s 代表 string ,亦即多少个字符; |
| %ni 那个 n 是数字, i 代表 integer ,亦即多少整数码数; |
| %N.nf 那个 n 与 N 都是数字, f 代表 floating (浮点),如果有小数码数, |
| 假设我共要十个位数,但小数点有两位,即为 %10.2f 啰! |
- eg:参考此链接

5.2 awk
| |
| |
| -1. 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中; |
| -2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作"; |
| -3. 做完所有的动作与条件类型; |
| -4. 若还有后续的“行”的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。 |
| |
| -1.NF:每一行($0)拥有的字段总数;$NF表示打印最后一个字段的值 |
| -2.NR:目前 awk 所处理的是“第几行”数据 |
| -3.FS:目前的分隔字符,默认是空白键 |
| |
| > 大于 < 小于 |
| >= 大于等于 <= 小于等于 |
| == 等于 !== 不等于 |
| |
| [root@localhost ddd] |
| root pts/0 192.168.15.1 Sun Apr 24 21:30 still logged in |
| root pts/1 192.168.15.1 Sat Apr 23 22:12 - 19:45 (21:33) |
| [root@localhost ddd] |
| root 192.168.15.1 |
| root 192.168.15.1 |
| |
| |
| |
| |
| [root@localhost ddd] |
| Name 1st 2nd 3th |
| VBird 23000 24000 25000 |
| DMTsai 21000 20000 23000 |
| Bird2 43000 42000 41000 |
| [root@localhost ddd] |
| Name 1st 2nd 3th Total |
| VBird 23000 24000 25000 72000.00 |
| DMTsai 21000 20000 23000 64000.00 |
| Bird2 43000 42000 41000 126000.00 |
| [root@localhost ddd] |
| Name 1st 2nd 3th Total |
| VBird 23000 24000 25000 72000.00 |
| DMTsai 21000 20000 23000 64000.00 |
| Bird2 43000 42000 41000 126000.00 |
6.文件比对工具
| 1.diff:以行为单位比对,通常用在同一文件的(或软件)的新旧版本差异上,也可以用做目录的比对;可以把新旧的版本差异 制作为补丁文件,再由补丁文件更新旧文件即可;可以友echo $?输出 |
| 2.cmp:主要是以字节为单位比对 |
| 3.patch:版本的更新与还原 与diff一起使用 |
| |
三、学习Shell Scripts
1.What is Shell Scripts
| 将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正则表达式、管线命令与数据流重导向等功能,以达到我们所想要的处理目的。 |
关于init(SystemV)和Systemd的介绍
关于换行符的介绍
| 1.关于编码:Dos和Windows采用回车+换行CR/LF表示下一行;而UNIX/Linux采用换行符LF表示下一行 |
| 2.scripts添加信息:功能、版本、作者信息、修改记录、需要的环境变量;最好使用vim |
| 3.调试:bash -x [filename] |
| 4.超出表达式递归:https://stackoverflow.com/questions/30404863/expression-recursion-level-exceeded |
| 5.filename=$ {fileuser:-"filename"} 若变量fileuser为空 ,则返回"filename".若变量 fileuser 有值,则返回其当前值;以确保变量一直有值 |
| 6.善于使用$? || 以及&&进行判断前一个指令回传至对于后一个指令是否要进行的依据;也可以使用test指令 |
| |
| |
| read -p "please input filename: " fileuser |
| filename=${fileuser:-"filename"} |
| |
| date1=$(date --date='1 days ago' +%Y%m%d) |
| date0=$(date +%Y%m%d) |
| |
| file1=${filename}_${date1} |
| file0=${filename}_${date0} |
| |
| touch "${file1}.log" |
| touch "${file0}.log" |
| |
| |
| read -p "input first number: " first_num |
| read -p "input second number: " sec_num |
| total=$((first_num * sec_num)) |
| echo -e "${first_num}*${sec_num}=${total}" |
| |
2.script的执行差异
- 利用bash(sh)来下达脚本时,改script是在子程序的bash内执行的,会使用一个新的bash环境;所以是script内的变量在bash环境下无效

- 利用source执行脚本,在父程序中执行,script中的变量会在bash中生效;source ~/.filename.sh

3.利用test指令的测试功能
主要进行数值、字符串和文件三个方面的检测
1.数值检测
| |
| -eq:值 1 等于值 2 |
| -ge : 值 1 大于或等于值 2 |
| -gt : 值 1 大于值 2 |
| -le : 值 1 小于或等于值 2 |
| -lt : 值 1 小于值 2 |
| -ne : 值 1 不等于值 2 |
2.比较文本
| |
| |
| ==:字符串 1 匹配字符串 2;;等号两边要有空格!!! |
| != : 字符串 1 与字符串 2 不匹配 |
| -n:字符串长度大于0 |
| -z:字符串长度等于 0 |
3.比较文件
| -ef:文件具有相同的设备和 inode 编号(它们是同一个文件) |
| -nt : 第一个文件比第二个文件新 |
| -ot:第一个文件比第二个文件旧 |
| -d:文件存在并且是目录(directory) |
| -e : 文件存在 |
| -f : 文件存在并且是文件(file) |
| -r:文件存在且可读 |
| -s:文件存在且大小大于零 |
| -w:文件存在且可写 |
| -x:文件存在且可执行 |
| |
| `优化1:[ "$a" == "$b" ] 优化 [ x"$a" == x"$b" ]:这种办法避免了$b为空的情况下 bash报错 |
| `优化2:[ x"$1" == x"1" ] 避免参数为空bash版本不兼容报错;但是也可以[ "$1" == ""] |
4.多个条件判断
| |
| |
| |
| |
| |
| |
| echo -e "Please input a filename, I will check the filename's type and permission. \n\n" |
| read -p "Input a filename : " filename |
| test -z ${filename} && echo "You MUST input a filename." && exit 0 |
| |
| test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0 |
| |
| test -f ${filename} && filetype="regulare file" |
| test -d ${filename} && filetype="directory" |
| test -r ${filename} && perm="readable" |
| test -w ${filename} && perm="${perm} writable" |
| test -x ${filename} && perm="${perm} executable" |
| |
| echo "The filename: ${filename} is a ${filetype}" |
| echo "And the permissions for you are : ${perm}" |
5.利用判断符号[]
- 必须要注意中括号的两端需要有空白字符来分隔
- 中括号内字符需要使用双引号
| |
| |
| |
| |
| read -p "input (Y/N): " yn |
| [ "$yn" == "N" ] || [ "$yn" == "n" ] && echo "NO, interrupert" && exit 0 |
| [ "$yn" == "Y" ] || [ "$yn" == "y" ] && echo "Yes, contine" && exit 0 |
4.Shell Scripts的默认变量 (0,1...)
| /path/to/scriptname opt1 opt2 opt3 opt4 |
| $0 $1 $2 $3 $4 |
| $0代表脚本文件名,接着的第一个参数就是$1 |
| $# :代表后接的参数“个数”,以上表为例这里显示为4; |
| $@ :代表“ "$1" "$2" "$3" "$4" ”之意,每个变量是独立的(用双引号括起来);和$*不同 记忆$@即可 |
| $* :代表“ "$1<u>c</u>$2<u>c</u>$3<u>c</u>$4" ”,其中 <u>c</u> 为分隔字符,默认为空白键, 所以本例中代表“ "$1 $2 $3 $4" ”之意。 |
| |
| #!/bin/bash |
| echo "the script name is $0" |
| [ "$#" -lt 2 ] && echo "less than 2" && exit 0 |
| echo "the whole(\$@) is $@" |
| echo "the 1st parameter(\$1) is $1" |
| |
| [root@localhost bin] |
| the script name is test.sh |
| the whole($@) is a b |
| the 1st parameter($1) is a |
5.条件判断式
5.1.利用if ....then
| if [ 条件判断式 ]; then |
| 当条件判断式成立时,可以进行的指令工作内容; |
| fi <==将 if 反过来写,就成为 fi 啦!结束 if 之意! |
| |
| #!/usr/bin/sh |
| read -p "input (Y/N): " yn |
| if [ "$yn" == "N" ] || [ "$yn" == "n" ] ; then |
| echo "NO, interrupert" |
| exit 0 |
| fi |
| if [ "$yn" == "Y" ] || [ "$yn" == "y" ] ; then |
| echo "Yes, contine" |
| exit 0 |
| fi |
| echo "Only y or n accepted" && exit 0 |
| |
| if [ 条件判断式一 ]; then |
| 当条件判断式一成立时,可以进行的指令工作内容; |
| elif [ 条件判断式二 ]; then |
| 当条件判断式二成立时,可以进行的指令工作内容; |
| else |
| 当条件判断式一与二均不成立时,可以进行的指令工作内容; |
| fi |
| |
| |
| read -p "input (Y/N): " yn |
| if [ "$yn" == "N" ] || [ "$yn" == "n" ] ;then |
| echo "NO, interrupert" && exit 0 |
| elif [ "$yn" == "Y" ] || [ "$yn" == "y" ] ;then |
| echo "Yes, contine" && exit 0 |
| else |
| echo "Only y or n accepted" && exit 0 |
| fi |
| |
| |
| process_chk_file=/home/ddd/process_chk.txt |
| netstat -antp > ${process_chk_file} |
| process_port=$(grep ":22" ${process_chk_file}) |
| if [ "${process_port}" = "" ] ; then |
| echo "Error,process SSH not runnning" |
| else |
| echo "Log,process SSH is running" |
| fi |
5.2.利用case...in...esac判断
| case $变量名称 in |
| 模式1) |
| command1 |
| command2 |
| ;; |
| 模式2) |
| command1 |
| command2 |
| ;; |
| *) |
| command1 |
| command2 |
| ;; |
| esac |
| #!/usr/bin/sh |
| read -p "input a num:" aNum |
| case $aNum in |
| 1) echo 'You select 1' |
| ;; |
| 2) echo 'You select 2' |
| ;; |
| *) echo 'You do not select a number between 1 to 4' |
| ;; |
| esac |
5.3.利用function功能
| #!/usr/bin/sh |
| function printit(){ |
| echo -n "ur choice is " |
| } |
| case ${1} in |
| "one") |
| printit; echo ${1} | tr 'a-z' 'A-Z' |
| ;; |
| *) echo 'over' |
| ;; |
| esac |
6.循环loop
6.1 while do done, until do done (不定循环)
| while [ "${yn}" != "yes" -a "${yn}" != "YES" ] |
| do |
| read -p "Please input yes/YES to stop this program: " yn |
| done |
| |
| until [ "${yn}" == "yes" -o "${yn}" == "YES" ] |
| do |
| read -p "Please input yes/YES to stop this program: " yn |
| done |
| |
| s=0 |
| i=0 |
| while [ "${i}" != "100" ] |
| do |
| i=$(($i+1)) |
| s=$(($s+$i)) |
| done |
6.2 for...in...do...done (固定循环)
| for var in con1 con2 con3 ... |
| do |
| 程序段 |
| done |
| |
| for animal in dog cat elephant |
| do |
| echo "There are ${animal}s.... " |
| done |
| |
| |
| |
| network="192.168.15" |
| ping_chk_file=/home/ddd/ping_chk_file_$(date +%Y%m%d).txt |
| [ ! -e "$ping_chk_file" ] && touch ${ping_chk_file} |
| |
| [ ! -s "$ping_chk_file" ] && echo "# ping-check" >> ${ping_chk_file} |
| echo "excuting" |
| for sitenu in $(seq 120 130) |
| do |
| ping -c 1 -w 1 ${network}.${sitenu} >/dev/null && result=0 || result=1 |
| if [ "$result" = 0 ] ; then |
| echo "$(date "+%Y-%m-%d %H:%M:%S"): server ${network}.${sitenu} is UP" >> ${ping_chk_file} |
| |
| else |
| echo "$(date "+%Y-%m-%d %H:%M:%S"): server ${network}.${sitenu} is DOWN" >> ${ping_chk_file} |
| |
| fi |
| done |
| |
| |
| |
| read -p "Please input a directory: " dir |
| if [ "${dir}" == "" -o ! -d "${dir}" ] ; then |
| echo "The ${dir} is NOT exist in your system." |
| exit 1 |
| fi |
| |
| filelist=$(ls ${dir}) |
| for filename in ${filelist} |
| do |
| perm="" |
| test -r "${dir}/${filename}" && perm="${perm} readable" |
| test -w "${dir}/${filename}" && perm="${perm} writable" |
| test -x "${dir}/${filename}" && perm="${perm} executable" |
| echo "The file ${dir}/${filename}'s permission is ${perm} " |
| done |
6.5 for...do...done 的数值处理
| for (( 初始值; 限制值; 执行步阶 )) |
| do |
| 程序段 |
| done |
| 这种语法适合于数值方式的运算当中,在 for 后面的括号内的三串内容意义为: |
| 初始值:某个变量在循环当中的起始值,直接以类似 i=1 设置好; |
| 限制值:当变量的值在这个限制值的范围内,就继续进行循环。例如 i<=100; |
| 执行步阶:每作一次循环时,变量的变化量。例如 i=i+1。 |
| |
| |
| read -p "input a num " nu |
| s=0 |
| for((i=1; i<=${nu}; i++)) |
| do |
| s=$((${s}+${i})) |
| done |
| echo "sum is ${s}" |
7.shell script的追踪与debug
| sh [-nvx] scripts.sh |
| 选项与参数: |
| -n :不要执行 script,仅查询语法的问题; |
| -v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上; |
| -x :将使用到的 script 内容显示到屏幕上,这是很有用的参数! |
四、补充
1.打印进度条
| #!/bin/sh |
| b='' |
| for ((i=0;$i<=100;i+=2)) |
| do |
| printf "progress:[%-50s]%s%%\r" $b $i |
| sleep 0.02 |
| b= |
| done |
| echo |
2.文件描述符(参考第一章18小节)
用途
/dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果,同样,/dev/null 在命令行和脚本中都非常有用/dev/null通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成,任何你想丢弃的数据都可以写入其中
丢弃标准输出、丢弃标准错误输出
在写shell脚本的时候,只想通过命令的结果执行后面的逻辑,而不想命令执行过程中有一大堆中间结果输出,这时候可以把命令执行过程中的输入全部写入 /dev/null
| |
| |
| command -v $1 >/dev/null |
| if [[ $? -eq 0 ]]; then |
| echo "command $1 exist..." |
| else |
| echo "command $1 not exist..." |
| fi |
| |
| |
| |
| rm $1 >/dev/null 2>$1 |
清空文件内容
cat /dev/null > t.txt
3.进程检测
| #!/bin/bash |
| |
| aboss5_flag=0 |
| aboss2_flag=1 |
| tomcat_flag=0 |
| mycat_flag=0 |
| |
| procmgr_ids=`ps -ef | grep procmgr | grep -v "grep" | awk '{print $2}'` |
| for id in $procmgr_ids |
| do |
| pathDir=`ls -al /proc/$id/cwd | awk '{print $NF}'` |
| echo [$id]:[$pathDir] |
| if [[ "$pathDir" == *"aboss5"* ]]; then |
| aboss5_flag=1 |
| echo "[NOTE] aboss5 procmgr is already started." |
| elif [[ "$pathDir" == *"aboss2"* ]]; then |
| aboss2_flag=1 |
| echo "[NOTE] aboss2 procmgr is already started." |
| fi |
| done |
4.关于双方括号
双方括号的用法说明
其他括号的用法说明
| #!/usr/bin/sh |
| |
| if [[ $1 == "s"* ]]; then |
| echo "s*" |
| elif [[ $1 == *"s" ]]; then |
| echo "*s" |
| elif [[ $1 == *"s"* ]] ;then |
| echo "*s*" |
| else |
| echo "none" |
| fi |
| |
| if [[ $1 == *"s"* ]]; |
| if [[ $1 == s* ]]; |
| if [[ $1 =~ sa* ]]; |
5.注释
| 1. |
| 2. :`多行注释` |
| 3. << BLOCK |
| 多行注释 |
| BLOCK |
6.引号
对于打印文本 单引号和双引号没有区别;打印输出一个已定义的变量,则需要使用双引号
| #!/usr/bin/sh |
| read -sp "num:" num |
| echo -e "\\n $num" |
7.关于日期格式化
| [root@localhost scripts] |
| 2022-05-06 00:14:42 |
| +%Y 年 2022 |
| m 月 01 |
| d 日 01 |
| H 时 二十四小时制 |
| M 分 |
| S 秒 |
8.sleep
| sleep 1d 2h 3m 30s 默认是秒 也可用作定时执行 不规范 |
五、案例
https://blog.csdn.net/u010230971/article/details/80335522
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!