在业务中经常会碰到需要shell编程的情况,想一次性学习shell编程的内容,相信对以后写一些自动化脚本会非常有帮助^_ ^
chmod +x ./test.sh #使脚本具有执行权限
# chmod 755 ./test.sh
./test.sh #执行脚本
- 定义变量时,变量名不加美元符号
- 变量名和等号之间不能有空格
- 使用一个定义过的变量,只要在变量名前面加美元符号即可
- 也可以加上花括号,也可以不加,加上花括号有利于编译器辩识变量的边界
appledeMacBook-Pro:shellCode_Study lvhongbin$ myName="lvhongbin"
appledeMacBook-Pro:shellCode_Study lvhongbin$ echo $myName
lvhongbin
appledeMacBook-Pro:shellCode_Study lvhongbin$ echo "My name is ${myName}"
My name is lvhongbin
- 字符串可以用单引号,也可以用双引号
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
appledeMacBook-Pro:shellCode_Study lvhongbin$ myName="lvhongbin"
appledeMacBook-Pro:shellCode_Study lvhongbin$ echo ${#myName}
appledeMacBook-Pro:shellCode_Study lvhongbin$ myName="lvhongbin"
appledeMacBook-Pro:shellCode_Study lvhongbin$ echo ${myName:0:2}
lv
参数类型 |
参数说明 |
= |
相等 |
!= |
不相等 |
-z |
字符串长度为0时为真 |
-n |
字符串长度不为0时为真 |
- 向脚本传递参数,脚本内获取参数的格式为:$n
- $0表示 要执行的第一个命令(不包括sh或者bash)
- $1表示 命令后的第一个参数
- $2,$3如此类推
参数类型 |
参数说明 |
$# |
参数的个数 |
$* |
以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$@ |
与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- |
显示Shell使用的当前选项,与set命令功能相同。 |
$? |
显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
chmod +x argus.sh
appledeMacBook-Pro:test lvhongbin$ ./argus.sh lv hong bin
This is commond: ./argus.sh
This is 1st arguements: lv
This is 2nd arguements: hong
This is 3rd arguements: bin
#! ./argus.sh
# author: lvhongbin
# description: receive outer arguments
echo "This is commond: $0"
echo "This is 1st arguements: $1"
echo "This is 2nd arguements: $2"
echo "This is 3rd arguements: $3"
- Shell 数组用括号来表示,元素用"空格"符号分割开
- 读取数组的时候还是用回中括号
- 也可以直接定义每个元素,如arr[0]=1
appledeMacBook-Pro:lego_docs lvhongbin$ p=(1 2 3)
appledeMacBook-Pro:lego_docs lvhongbin$ echo ${p[0]}
1
- 使用@ 或 * 可以获取数组中的所有元素,如arr[@], arr[*]
- 类似toString方法打印,但是连接各个元素的是空格
appledeMacBook-Pro:lego_docs lvhongbin$ echo ${#p[*]}
3
appledeMacBook-Pro:lego_docs lvhongbin$ echo ${#p[#]}
-bash: #: syntax error: operand expected (error token is "#")
appledeMacBook-Pro:lego_docs lvhongbin$ echo ${#p[@]}
3
- 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用
- 下面使用expr举例
- 注意算数式左右使用的是反上引号
- 注意二元运算符左右需要有一个空格
appledeMacBook-Pro:lego_docs lvhongbin$ echo `expr 1 + 2`
3
appledeMacBook-Pro:test lvhongbin$ i=0 ; i=`expr $i + 1`
appledeMacBook-Pro:test lvhongbin$ ${i}
1
参数类型 |
参数说明 |
举例 |
+ |
加法 |
`expr $a + $b` 结果为 30。 |
- |
减法 |
`expr $a - $b` 结果为 -10。 |
* |
乘法 |
`expr $a * $b` 结果为 200。 |
/ |
除法 |
`expr $b / $a` 结果为 2。 |
% |
取余 |
`expr $b % $a` 结果为 0。 |
= |
赋值 |
a=$b 将把变量 b 的值赋给 a。 |
== |
相等 |
用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。 |
!= |
不相等 |
用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。 |
参数类型 |
参数说明 |
举例 |
-eq |
检测两个数是否相等,相等返回 true。 |
[ $a -eq $b ] 返回 false。 |
-ne |
检测两个数是否不相等,不相等返回 true。 |
[ $a -ne $b ] 返回 true。 |
-gt |
检测左边的数是否大于右边的,如果是,则返回 true。 |
[ $a -gt $b ] 返回 false。 |
-lt |
检测左边的数是否小于右边的,如果是,则返回 true。 |
[ $a -lt $b ] 返回 true。 |
-ge |
检测左边的数是否大于等于右边的,如果是,则返回 true。 |
[ $a -ge $b ] 返回 false。 |
-le |
检测左边的数是否小于等于右边的,如果是,则返回 true。 |
[ $a -le $b ] 返回 true。 |
参数类型 |
参数说明 |
举例 |
! |
非运算,表达式为 true 则返回 false,否则返回 true。 |
[ ! false ] 返回 true。 |
-o |
或运算,有一个表达式为 true 则返回 true。 |
[ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a |
与运算,两个表达式都为 true 才返回 true。 |
[ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
appledeMacBook-Pro:~ lvhongbin$ if [ 13 -eq 13 ]; then echo "13 -eq 13 : 13 等于 13"; fi
13 -eq 13 : 13 等于 13
- 使用双括号而非单括号,单括号会报错
- 括号内边需要有空格进行分割
参数类型 | 参数说明 | 举例
-|-|-
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true
- 这是最简单的功能
- 加上参数-e 表示字符串转义字符生效,但前提是加上单引号或者是双引号
appledeMacBook-Pro:test lvhongbin$ echo asd\nsda
asdnsda
appledeMacBook-Pro:test lvhongbin$ echo -e asd\nsda
asdnsda
appledeMacBook-Pro:test lvhongbin$ echo -e 'asd\nsda'
asd
sda
appledeMacBook-Pro:test lvhongbin$ echo -e "asd\nsda"
asd
sda
appledeMacBook-Pro:test lvhongbin$ echo "asd\nsda"
asd\nsda
appledeMacBook-Pro:test lvhongbin$ ls
0.2.8_0.crx argus.sh myProject package.json
0.2.8_0.pem file node_modules
ab.js lego-sdk-tool.zip package-lock.json
appledeMacBook-Pro:test lvhongbin$ touch echo
appledeMacBook-Pro:test lvhongbin$ echo "i love you" > echo
appledeMacBook-Pro:test lvhongbin$ cat echo
i love you
- 不自动换行
- 不需要添加参数-e便可使用转义符号
- 可以添加格式替代符:-表示左对齐,没有-表示右对齐,
appledeMacBook-Pro:test lvhongbin$ printf "%-10s %5s\n" 姓名 年龄; printf "%-10s %5d\n" John 20; printf "%-10s %5d\n" Apple 100 ; printf "%-10s %5d\n" Mike 20; printf "%-10s %5d\n" lvhongbin 40
姓名 年龄
John 20
Apple 100
Mike 20
lvhongbin 40
- 用于检查字符串(采用=和!=),数字(采用-英文字母)和文件
- 相当于[ ]符号
- 用在if语句中
appledeMacBook-Pro:test lvhongbin$ if test 3 -eq 4 ; then echo "3 == 4" ; else echo "3 != 4" ; fi
3 != 4
参数类型 |
参数说明 |
-eq |
相等 |
-ne |
不相等 |
-gt |
大于 |
-ge |
大于或等于 |
-lt |
小于 |
-le |
小于或等于 |
参数类型 |
参数说明 |
= |
相等 |
!= |
不相等 |
-z |
字符串长度为0时为真 |
-n |
字符串长度不为0时为真 |
参数类型 |
参数说明 |
-e |
文件存在为真 |
-r |
文件存在且可读为真 |
-w |
文件存在且可写为真 |
-x |
文件存在且可执行为真 |
-d |
文件存在且为目录为真 |
-f |
文件存在且为普通文件为真 |
-c |
文件存在为字符型特殊文件为真 |
-b |
文件存在为块特殊文件为真 |
- if [ ] ; then xxx ; elif [ ] ; then xxx ; else xxx ; fi
- 写在脚本里面则是
if [ ]
then
xxx
elif [ ]
then
xxx
else
xxx
fi
- for var in xxx xxx xxx xxx ... ; do xxx xxx xxx ; done
- 不适用于循环
- 只能一条路走到底
appledeMacBook-Pro:test lvhongbin$ for var in 1 2 3 4 5 ; do echo $var ; done
1
2
3
4
5
- while condition ; do xxx xxx xxx ; done
appledeMacBook-Pro:~ lvhongbin$ i=0
appledeMacBook-Pro:~ lvhongbin$ while [ $i -lt 10 ]; do A[$i]=`expr $i + 1`; let i++; done
appledeMacBook-Pro:~ lvhongbin$ echo ${A[1]}
2
appledeMacBook-Pro:~ lvhongbin$ echo ${A[2]}
3
appledeMacBook-Pro:~ lvhongbin$ i=0
appledeMacBook-Pro:~ lvhongbin$ while [ $i -lt 10 ]; do echo ${A[$i]}; let i++; done
1
2
3
4
5
6
7
8
9
10
- 直到满足条件才退出
- 初始化条件跟循环语句不能写在同一行
appledeMacBook-Pro:test lvhongbin$ b=0
appledeMacBook-Pro:test lvhongbin$ until [ $b -gt 10 ] ; do echo $b ; b=`expr $b + 1` ; done
- 参数用$1, $2...
- 因为第一个参数是$0 是bash
appledeMacBook-Pro:~ lvhongbin$ function func(){ printf "%-5s %-5d\n" $1 $2; }
appledeMacBook-Pro:~ lvhongbin$ func xiaohong 10
xiaohong 10
appledeMacBook-Pro:~ lvhongbin$ function func(){ printf "%-5s %-5d\n" $0 $2; }
appledeMacBook-Pro:~ lvhongbin$ func xiaohong 10
-bash 10
appledeMacBook-Pro:~ lvhongbin$ function func(){
> echo "i love you"
> }
appledeMacBook-Pro:~ lvhongbin$ func
i love you
参数类型 |
参数说明 |
$# |
传递到脚本的参数个数 |
$* |
以一个单字符串显示所有向脚本传递的参数 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$@ |
与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- |
显示Shell使用的当前选项,与set命令功能相同。 |
$? |
显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
- 主要以大于号小于号为主,所以在做数字比较的时候不能使用大于号小于号
参数类型 |
参数说明 |
command > file |
将输出重定向到 file。 |
command < file |
将输入重定向到 file。 |
command >> file |
将输出以追加的方式重定向到 file。 |
n > file |
将文件描述符为 n 的文件重定向到 file。 |
n >> file |
将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m |
将输出文件 m 和 n 合并。 |
n <& m |
将输入文件 m 和 n 合并。 |
<< tag |
将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
appledeMacBook-Pro:test lvhongbin$ echo "i love you" >> argus.sh
appledeMacBook-Pro:test lvhongbin$ cat argus.sh
-bash: ./ab.js: Permission denied
i love you
appledeMacBook-Pro:test lvhongbin$ echo "i love you" > argus.sh
appledeMacBook-Pro:test lvhongbin$ cat argus.sh
i love you
- 将 stdout 和 stderr 合并后重定向到 file
$ command > file 2>&1
或者
$ command >> file 2>&1
> - command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
$ command < file1 >file2
appledeMacBook-Pro:test lvhongbin$ wc -l < argus.sh >> ab.js
appledeMacBook-Pro:test lvhongbin$ cat ab.js
const i = require('@baidu/lego-events-base-util-plat_test');
console.log(i); 1
> - Here Document 可以讲两个断点标志位中间的内容全部给到它前面的命令 wc -l
appledeMacBook-Pro:test lvhongbin$ wc -l << EOF
> nihao
> woshi
> lvhongbin
> EOF
3
- /dev/null 可以讲不想在屏幕上显示的内容重定向该文件上,这是一个特殊的文件,所有的内容输入到这里都会被丢掉,像个黑洞一般,吞噬所有文字
参数类型 |
参数说明 |
?word |
向下搜索 |
/word |
向上搜索 |
:n1,n2s/word1/word2/g |
在n1到n2行中将word1替换成word2 |
:1,$s/word1/word2/g |
在1到最后一行中将word1替换成word2 |
参数类型 |
参数说明 |
dd |
删除光标所在行 |
ndd |
向下删除n行 |
dG |
删除光标所在到最后一行的所有数据 |
d$ |
删除游标所在处,到该行的最后一个字符 |
参数类型 |
参数说明 |
yy |
复制光标所在行 |
nyy |
向下复制n行 |
yG |
复制光标所在到最后一行的所有数据 |
y$ |
复制游标所在处,到该行的最后一个字符 |