Shell 脚本在我们日常开发和学习都有举足轻重的地位,比如看一些开源项目,比如项目中的各式各样的脚本,对于促进生产力工具有很大帮助!而且shell最大的好处就是依赖比较小,直接可以运行!
1、命令小技巧
1、-x
命令进行跟踪调试执行
1 | !/bin/sh |
执行:
1 | ➜ note git:(master) ✗ sh -x /Users/fanhaodong/Desktop/project/test.sh |
2、-c
命令 (执行命令参数)
1 | ➜ note git:(master) ✗ sh -c << EOF " |
- 这种经常会在网上下载一个脚本然后直接执行,可以
sh -c "curl xxxx.sh"
3、使用set变量
一般就是 set -ex ,或者执行的时候 bash -ex
1 | !/bin/sh |
执行
1 | ➜ makefile git:(master) ✗ sh ./main.sh |
帮助可以看: sh -c "help set"
2、语法小技巧
1、引用变量
一般推荐正确用法是,变量使用 ""
双引号引用,其次就是变量使用 ${}
进行引用!very good!
1 | 使用 ${} 引用变量,拒绝歧义 |
2、 $( cmd )
和 `cmd` 执行命令
1 | ➜ ~ echo $(uname) |
3、 cat [>>|>] [file] << EOF .... EOF
写入文件
如果重定向的操作符是<<-,那么分界符(EOF)所在行的开头部分的制表符(Tab)都将被去除。这可以解决由于脚本中的自然缩进产生的制表符。
1 | ➜ test cat > glide.yaml << EOF |
4、管道符 和 xargs
1. 管道符
管道符作用就是把上一个命令的标准输出作为下一个命令个标准输入
1 | ➜ echo "hello wrold" | python -c 'import sys; print(sys.stdin.read())' |
2. xargs
1 .xargs
的作用就是把上个命令的标准输出 作为 下一个命令的参数
1 | ➜ echo "hello wrold" | xargs python -c 'import sys; print(sys.argv)' |
- 如果想替换分隔符号需要输入参数
-d
, 同时你想打印所执行的命令-t
1 | ➜ ~ echo "hello:wrold" | xargs -t -d ':' python -c 'import sys; print(sys.argv)' |
- xargs 是并行执行的,可以通过如下测试**,
-P
等于0表示不限制进程数**,默认是1,-n
等于1表示参数按每一个进行拆分
这个命令相当棒,就是可以并行执行!
1 | ➜ echo "hello world" | xargs -P0 -n1 sh -c 'echo "start $$"; sleep 5s; echo "end $$"' |
-I
,可以替换命令行参数
1 | ➜ ~ echo "hello wrold" | xargs echo |
5、特殊变量
$0
: 当前脚本的文件名$n
: 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。$#
: 传递给脚本或函数的参数个数。$*
: 传递给脚本或函数的所有参数。$@
: **传递给脚本或函数的所有参数(推荐使用这个)**,当使用""
双引号引用是$*
会变成字符串而不是数组$?
: 上个命令的退出状态,或函数的返回值。一般情况下,大部分命令执行成功会返回 0,失败返回 1。$$
: 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
6、[[]]
和 []
标准 以及基本语法规范
具体规范: https://github.com/koalaman/shellcheck/wiki/SC2039
1 | !/bin/sh |
执行后发现
7、/bin/sh 与 /bin/bash 的区别
3、获取命令结果 $(cmd)
有两种写法,一种是 $()
这个并不是所有的shell都支持,但是比较直观, 另外一种是 "``"
(它可是适用更多的平台)
1 | !/bin/sh |
输出:
1 | . .. .DS_Store 1714.jpg docker-rocketmq-cluster gridea-home hexo-home note pdf vuepress-starter |
4、输入输出重定向 2>&1
使用
程序中经常有,标准输出,但是还有错误输出,因此需要合并到一个流中
其实Go的程序中正执行脚本的时候可以指定,标准输出和错误输出
1 | command := exec.Command(shell, "-c", cmd) |
使用的时候:
- 默认为标准输出重定向,与 1> 相同
2>&1
意思是把 标准错误输出 重定向到 标准输出.&>file
意思是把标准输出和标准错误输出 都重定向到文件file中
例如:
command >out.file 2>&1 &
command >out.file是将command的标准输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。最后一个&
,是让该命令在后台执行。
参考
https://www.cnblogs.com/caolisong/archive/2007/04/25/726896.html
5、If语句
if 其实就是
test
命令
1、格式
- 换行写
1 | if [ condition ]; then |
2)非换行写
1 | if [ -f "/Users/fanhaodong/note/note/Makefile1" ]; then echo 111 ; echo 222 ;elif [ -f "/Users/fanhaodong/note/note/README.md" ]; then echo 333 ; echo 4444 ; else echo 555 ; echo 666 ; fi |
2、结果获取/判断
结果输出0 ,表示为真,可以通过$?
来获取结果
3、例如调试条件
1 | ➜ note git:(master) ✗ test "abc"!="def" |
4、测试文件是否存在
- 如果你要判断一个文件是否存在,只需要
-e
即可,输出0
表示文件存在 (不在判断类型的时候推荐使用这个) - 如果你要判断一个文件是否为文件夹,并且判断是否存在,只需要
-d
即可 - 如果你要判断一个文件是否为
常规文件
,并且判断是否存在,只需要-f
即可 - -L filename 如果 filename为符号链接,则为真
1 | [root@019066c0cd63 ~]# ls -al |
- -r filename 如果 filename可读,则为真
- -w filename 如果 filename可写,则为真
- -x filename 如果 filename可执行,则为真
- -s filename 如果文件长度不为0,则为真
- -h filename 如果文件是软链接,则为真
1 | ➜ note git:(master) ✗ [ -f "/Users/fanhaodong/note/note/Makefile" ] |
5、字符串操作
字符串推荐加
""
进行定义
- 判断字符串是否为空
-z
(zero)么
1 | !/bin/sh |
2)判断两个字符串是否相同
1 | !/bin/sh |
4、测试一个命令是否存在 command -v $#
1 | !/bin/sh |
5、获取字符串长度 ${#var}
1 | !/bin/sh |
6、数字比较
- -eq 等于
- -ne 不等于
- -gt 大于
- -ge 大于等于
- -lt 小于
- -le 小于等于
1 | !/bin/sh |
7、shell脚本中if判断’-a’ - ‘-z’含义
https://blog.csdn.net/tootsy_you/article/details/95597376
6、for循环
1、for <item> in <items> ; do <script1>; <script2>;done
1 | !/bin/bash |
2、for((x=0; x<10; x++));do <script1>; <script2>; done
1 | for((x=0; x<10; x++));do echo "$x" ;done |