Shell脚本
原创声明:作者:陈咬金、 博客地址:https://www.cnblogs.com/zh94/
原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/e1007d5a-4ec0-4ee7-98a0-e82989f0bffb
mkdir
touch newFile 或 vim newFile
chmod 755 newFile
rm -rf newFile
sudo sh -c
find / -name kb-core
which bash
bash特殊字符上
; 可以在同一行上写两个或者两个以上的命令
;; 双分号可以用于终止case选项
' '单引号',直接认为变量只是一个字符,将会阻止STRING中所有特殊字符的解释
" "双引号",变量引用时,还是显示变量的值,将会阻止(解释)STRING中大部分特殊的字符
/ 斜线/,表示路径符,/bin/bash,多个/或者//,////bin/////bash 表示的含义于单斜线含义相同,
\ 反 斜线,表示转义符号,\n ,\',\",
` 反序号,反序号的命令会被优先执行;cp `mkdir back` test.sh back,表示先创建back文件夹再将test.sh拷贝到back目录下;
: 冒号,一个什么都不做的命令,等价于shell中的true,
while :
do
echo "endless loop"
done
可以在if/then中做占位符
condition=5
if [ $condition -gt 0 ]
then : # 什么都不做,退出分支
else
echo "$condition"
fi
变量扩展
$ : > test.sh # 文件“test.sh”现在被清空了
# 与 cat /dev/null > test.sh 的作用相同
# 然而,这并不会产生一个新的进程, 因为“:”是一个内建命令
bash特殊字符下
小括号 () :在小括号中的变量将会按照一个子shell运行,且可以定义初始化数组
#! /bin/bash
#作为子shell运行,
a=123
( a=321; )
echo "$a" #a的值为123而不是321,因为括号将判断为局部变量
#定义为数组
array=(1 2 3);
echo ${array[2]} #输出 3
中括号 [] :1. 条件表达式放置到中括号中,第二,如上,直接数组取值也是使用的[]中括号
a=5
if [ $a -lt 10 ]
then
echo "a: $a"
else
echo 'a>10'
fi
大括号 {} :1.匿名代码块,2.文件名扩展
a=123
{ a=321; }
echo "a = $a" #输出结果为321,匿名代码块中所声明的变量,对于脚本的其他部分是可见的,于子shell小括号()的使用方式不同,需注意;
touch t.txt
cp t.{txt,back} #复制t.txt的内容复制到t.back文件中,等同于 cp t.txt t.back ,直接cp拷贝的方式,会将当前文件的权限,也会拷贝到新的文件中,如果是使用cat t.txt >> t.back,则只是将t.txt中的内容拷贝到一个新的文件t.back中,并不具备执行等权限;需重新使用chmod赋值部分权限即可;
变量和参数
变量定义:
变量定义时=等号双边不能存在空格,如:name="test",命名规则参考Java即可;
变量的使用:
变量的使用可以使用 $name的方式进行引用,或${name},帮助识别变量的边界,如${name}123,如不加花括号,则解释器会把 name123当做一个变量名称来引用;
只读变量:name="test" ; reaonly name 则表示当前name变量为只读变量,后续不会被更改,否则异常提示;
位置参数:
./test.sh 参数1 参数2 参数3 通过这种方式传参,则在对应的脚本中通过 $1,$2 的方式来获取对应的脚本启动时的参数启动值;如下说明:
从命令行传递到脚本的参数:$0,$1,$2,$3...
$0就是脚本文件自身的名字,$1 是第一个参数,$2 是第二个参数,$3 是第三个参数,然后是第四个。$9 之后的位置参数就必须用大括号括起来了,比如,${10},${11},${12}。
$# : 传递到脚本的参数个数
$* : 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过 9个
$$ : 脚本运行的当前进程 ID号
$! : 后台运行的最后一个进程的进程 ID号
$@ : 与$*相同,但是使用时加引号,并在引号中返回每个参数
$: 显示shell使用的当前选项,与 set命令功能相同
$? : 显示最后命令的退出状态。 0表示没有错误,其他任何值表明有错误。
基本运算符
算数运算符:(使用 expr 作为计算工具)
注意事项:
1. 表达式和运算符之间要有空格,如:sum=`expr $a + $b`
2. 使用乘法计算时,需使用 \ 转义:如:sum=`expr $a \* $b`
3. 使用条件表达式的时候:[$a == $b],其中条件表达式和算数运算一样,都需要中间有空格存在,而赋值运算符,a=2,则不能存在空格符号;
关系运算符:(只支持数字,不支持字符串,除非字符串也是数字)
-eq 检测两个数是否相等,相等则返回true
-ne 检测两个数是否相等,不相等返回true
-gt 左边数是否大于右边,大于则返回true
-lt 左边数是否小于右边,小于则返回true
-ge 左边数是否大于等于右边,大于等于则返回true
-le 左边数是否小于等于右边,小于等于则返回true
if[$a -eq $b]
then
echo 'a等于b'
else
echo 'a不等于b'
fi
逻辑运算符:(&& ,|| )
if [[$a -eq 100 && $b -eq 100 ]]
then
echo 'true'
else
echo 'false'
fi
字符串运算符:(只适合字符串比对时使用)
= 检测两个字符串是否相等,相等返回true
!= 检测两个字符串是否相等,不相等则返回true
-z 检测字符串长度是否为0,为0则返回true
-n 检测是否为0,不为0则返回true
str 检测字符串是否为空,不为空则返回true
a='abc'; b='efg';
#判断两个字符串是否相等
if[$a = $b]
then
echo '两字符串相等'
else
echo '两字符串不同'
fi
#判断字符串长度是否为0
if[-n $a]
then
echo '$a字符串长度不等于0'
else
echo '$a长度为0'
fi
#判断字符串是否为空,默认为 str 运算符
if[$a]
then
echo '字符串不为空'
else
echo '字符串为空'
fi
文件测试运算符:()
-r file
检测文件是否可读,如果是,则返回 true。
[ -r $file ] 返回 true。
-w file
检测文件是否可写,如果是,则返回 true。
[ -w $file ] 返回 true。
-x file
检测文件是否可执行,如果是,则返回 true。
[ -x $file ] 返回 true。
-s file
检测文件是否为空(文件大小是否大于0),不为空返回 true。
[ -s $file ] 返回 true。
-e file
检测文件(包括目录)是否存在,如果是,则返回 true。
[ -e $file ] 返回 true。
流程控制
if else(语法注意事项:if空格[空格$a -eq $b空格)需注意空格部分,条件表达式的变量比对前后,都需要增加空格,否则语法错误异常)
$a=2;$b=3
#直接if else 的写法
if [ $a -eq $b ]
then
echo 'a==b'
else
echo 'a!=b'
fi
#if else if 的写法
if [ $a -eq $b ]
then
echo 'a==b'
elif [ $a -gt $b ]
then
echo 'a>b'
else
echo 'a!=b'
fi
# if 嵌套if 的写法
if [ $a -eq $b ]
then
if [ $a -eq $b ]
then
echo '双重if判断a==b'
fi
fi
# 使用test 用来表示条件表达式,如上述的判断语句直接将对应的 [ ] 中括号部分代替为test即可
if test $a -eq $b
then
echo 'a==b'
fi
#in关键词后面跟所要循环的变量,var表示所循环的变量所对应的关键词(注:实际上只要为空格分离的数据皆为可循环的数组)
for var in 1 2 3 4
do
echo "DATA:$var" #输出结果为 1 2 3 4
done
#也可以直接使用数组进行循环
nums=(10 20 30) #需注意的是,此处创建数组时,数组中的内容为空格分离,而并非逗号分隔,逗号分隔则为一个整体,并非数组结构
for var in ${nums[*]} #此处循环数组结构时,使用nums[*]表示得到当前数组中的所有数据内容,否则则默认获取第一条数据,即10;详情可查看shell #中关于数组的介绍;而之所以使用${nums[*]},而并非 $nums[*],是因为需要使用{}大括号来表示变量整体,帮助识别变量边 #界,上述变量中有所介绍 end;
do
echo $var #输出结果为 10 20 30
done
#当然也可以直接获取当前shell启动时所获取的参数进行循环,如下:
./test.sh 100 200
for var in $*
do
echo $var #输出结果为100 200
done
while ; # 此处 ; 表示空命令,类似于此处的true
do
do
echo '不断输出' #则将会不间断输出该内容,
done
#通过循环的方式不断的接受所输入的参数,并判断如果为quit时,则退出当前程序;
while read data #read data 表示读取键盘所输入的值,此处通过循环执行,则输入一次结果则判断一次,直到符合规定为止(此处为举例,应用场景有很多)
do
if [ $data = 'quit' ]
then
echo '退出成功'
exit 0
fi
done
#判断变量是否满足条件,并循环++
var=1
while(( $var<=5 )) #关于(())双括号的结构语句:https://www.cnblogs.com/linuxprobe/p/5634208.html
do
echo $var
let "var++" #let 是和expr 相同的四则运算符号,https://www.cnblogs.com/zwgblog/p/6005822.html
done
read data #读取对应的输入值
case $data in
case $data in
1) echo "$data 所对应的值为1" ;; #判断当前输入值是否为1,每一个模式后必须以 )有括号结束;
2) echo "$data 所对应的值为2" ;; # ;; 表示执行当前模式后,则结束以下递推再执行的操作,类似于其他程序中case所对应的break;
3|4|5) echo "$data 所对应的值为3-5之间" ;; # 表示当前的输入值在 3|4|5任何一项时则满足当前case,进入当前模式执行
*) echo "$data 值为其它";; # 当所对应的值为其它时,*表示获取所有数值,再执行对应的命令;
esac # 结尾使用 case的反向英文,esac表示case语句的结尾;
var=1
while (( $var<=5 ))
do
let "var++"
if test $var -eq 3
then
echo 'stop ++'
continue #此处continue则表示跳出当前循环,continue后的代码将不会被执行,输出结果为:2,stop++,4,5,6
#此处更改为break则直接停止当前循环,输出结果为 2,stop++
fi
echo $var
done
函数结构
函数定义(1. 所有函数在使用前必须先定义,也就是先定义,再使用;2. 函数返回值在“函数调用后”通过 $? 来获取数据,3.return 数值必须为数字(0-255之间))
demoFun(){
echo "$1 + $2" # $1表示获取当前传参的一个数值,方法参数的获取方法于脚本中传参的获取方式相同; #获取超过第10个参数时需要使用${10}使用{}取变量值的分界线
echo "$1 + $2" # $1表示获取当前传参的一个数值,方法参数的获取方法于脚本中传参的获取方式相同; #获取超过第10个参数时需要使用${10}使用{}取变量值的分界线
return 23 #表示调用方法后的返回值,也可以不使用return,
}
demoFun 30 50 #表示调用demoFun方法,并传参30 和 50
echo $? #函数返回值在调用该函数后,使用 $? 来获取,此处输出函数调用后的返回值,输出结果为 23;
双括号结构语句(( ))
双括号语句,作用还是很重要****的****https://www.cnblogs.com/linuxprobe/p/5634208.html