shell基础
重点
变量可以存变量,但是源变量的值变化以后,目标变量的值不变
子进程不能继承父进程的变量
脚本执行的过程是开启了一个临时的子进程执行,用 .空格sh source空格sh 可以在父进程执行
| 管道符号后边的会变为一个子进程去执行
profile profile.d/ 定义环境变量,执行脚本
bashrc 定义本地变量,定义函数
continue 不执行本次循环,继续循环其他
break 退出整个循环,执行其他脚本
shift 把未使用的参数往前挪一位
##################################################################################
(括号里的变量赋值是临时性的 执行完就没有了)
[root@rocky ~]# name=wang ; (echo $name;name=shuai;echo $name); echo $name
wang
shuai
wang
##################################################################################
{花括号的变量是在当前环境执行,是生效的}
[root@rocky ~]# name=wang ; { echo $name;name=shuai;echo $name ;}; echo $name
wang
shuai
shuai
[root@rocky ~]#
##################################################################################
安全机制
set -e #如果一个命令返回一个非0退出状态值就退出
set -u #在扩展一个没有设置的变量时,显示错误信息
set -x #在执行命令时,打印命令及参数 类似 bash -x
组合使用 set -e -u
编程基础
低级语言
二进制
汇编语言
高级语言
编译:高级语言-->编译器-->机器代码文件-->执行 c,c++
解释:高级语言-->执行-->解释器-->机器代码 shell python php javascript perl
脚本执行方法
.
./
bash
sh
cat 1.sh | bash
bash < 1.sh
curl -s http://wsb/1.sh | bash
###############################################
bash -n 检查脚本语法
bash -x 脚本执行过程
变量
a=`ls` a=$(ls)
显示环境变量 env declare export
查看当前变量 set
export 设置环境变量
declare -x 设置环境变量
declare -r 设置只读变量
declare -i 设置变量为数字
declare -l 设置变量小写
declare -u 设置变量大写
declare -A 设置变量为关联数组#自定义名称的数组
declare -a 设置变量为数组
readonly 设置只读变量
local 本地变量
位置变量
$1,$2,$3,$4 第一个参数..第二个参数....第四个参数
$$ 脚本的PID
$@ 所有参数
$# 参数的数量
$0 脚本的文件名
!$ 上个命令的参数
exit 111 设置返回状态码
高级变量
var={str-expr}
[root@rocky ~]# unset name; wang=${name-"haha"};echo $wang
haha
[root@rocky ~]# name=""; wang=${name-"haha"};echo $wang
[root@rocky ~]# name=hi; wang=${name-"haha"};echo $wang
hi
------------------------------------------------------
var={str:-expr}
[root@rocky ~]# unset name; wang=${name:-"haha"};echo $wang
haha
[root@rocky ~]# name=""; wang=${name:-"haha"};echo $wang
haha
[root@rocky ~]# name=hi; wang=${name:-"haha"};echo $wang
hi
变量配置方式 | str没有配置 | str为空字符串 | str已配置非空字符串 |
---|---|---|---|
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr var=expr | str不变 var= | str不变 var=$str |
var=${str:=expr} | str=expr var=expr | str=expr var=expr | str不变 var=$str |
var=${str?expr} | expr输出至stderr | var= | var=$str |
var=${str:?expr} | expr输出至stderr | expr输出至stderr | var=$str |
eval
首先会扫码命令行所有的置换,然后在执行命令#适用于对变量二次执行的命令
例
[root@rocky ~]# n=10
[root@rocky ~]# echo {1..$n}
{1..10}
[root@rocky ~]# eval echo {1..$n}
1 2 3 4 5 6 7 8 9 10
[root@rocky ~]#
间接变量引用
[root@rocky ~]# a=b
[root@rocky ~]# b=ab
[root@rocky ~]# echo $a #无效
b
[root@rocky ~]# echo $b
ab
[root@rocky ~]# echo ${!a}
ab
[root@rocky ~]# eval echo \$$a
ab
printf
%s 字符串
%d,%i 十进制整数
##########################
默认右对齐
- 左对齐
%-10s表示十个字符宽左对齐
%-3s 表示三个字符宽右对齐
“\n” 换行
[root@rocky ~]# printf %05s"\n" 1 2 3
1
2
3
[root@rocky ~]# printf %-05s"\n" 1 2 3
1
2
3
[root@rocky ~]#
[root@rocky ~]# printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70 小红 女 18 50
姓名 性别 年龄 体重
小明 男 20 70
小红 女 18 50
算数运算
declare -i a=1+2
let a=1+2
echo 1+2 | bc
a=$((1+3))
a=$[2*4]
% 取余数 %10 小于10的数
/ 除
* 成
+ 加
- 减
+= i+=10 相当于i=i+10
-= i-=j 相当于i=i-j
/=
*=
++ i++, ++i 相当于i=i+1
-- i--, --i 相当于i=i-1
[root@rocky ~]# a=1
[root@rocky ~]# echo $a
1
[root@rocky ~]# let a+=10
[root@rocky ~]# echo $a
11
[root@rocky ~]# let a--
[root@rocky ~]# echo $a
10
[root@rocky ~]# let --a
[root@rocky ~]# echo $a
9
###########################
[root@rocky ~]# a=1
[root@rocky ~]# echo $a
1
[root@rocky ~]# let b=a++
[root@rocky ~]# echo $b
1
[root@rocky ~]# echo $a
2
[root@rocky ~]#
########################
read
-p #加提示
[root@rocky shell]# read NAME AGE
wang 18
[root@rocky shell]# echo $NAME $AGE
wang 18
test判断
用法[ -e /etc/passwd ]
help test
-a FILE True if file exists.
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-O FILE True if the file is effectively owned by you.
-G FILE True if the file is effectively owned by your group.
-N FILE True if the file has been modified since it was last read.
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
modification date).
FILE1 -ot FILE2 True if file1 is older than file2.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set.
-R VAR True if the shell variable VAR is set and is a name
reference.
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
help [[
[root@rocky ~]# help [[
[[ ... ]]: [[ expression ]]
Execute conditional command.
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators:
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
EXPR1 && EXPR2 True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2 True if either EXPR1 or EXPR2 is true; else false
When the `==' and `!=' operators are used, the string to the right of
the operator is used as a pattern and pattern matching is performed.
When the `=~' operator is used, the string to the right of the operator
is matched as a regular expression.
The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
determine the expression's value.
Exit Status:
0 or 1 depending on value of EXPRESSION.
用法1
[root@rocky ~]# name=mage ;[[ $name == m* ]] ;echo $?
0
[root@rocky ~]# name=mage ;[[ $name == am* ]] ;echo $?
1
用法2
[root@rocky ~]# name=mage ;[[ $name =~ ^m ]] ;echo $?
0
[root@rocky ~]# name=mage ;[[ $name =~ ^m$ ]] ;echo $?
1
[root@rocky ~]# name=mage ;[[ $name =~ ^mage$ ]] ;echo $?
0
[root@rocky ~]# name=mage ;[[ $name =~ ^mag$ ]] ;echo $?
1
[root@rocky ~]# name=mage ;[[ $name =~ ^mag$ ]] ;echo $?
for
for i ;do 如果不指定变量值 默认$i 就是$@所有参数
for ((exp1;exp2;exp3));do commands;done
for name in exp1;do commands;done
while
while cmd1;do cmd2;done
while read i ;do 循环体 done < /etc/passwd
函数
help function
#注: 在函数里加local就不会影响函数外的变量值
#注: 在函数里如果调用自己的函数会无线循环
func_name () { local name=wang;echo $name };func_name
语法1 func_name () {
函数体
}
语法2 function func_name {
函数体
}
语法3 function func_name(){
函数体
}
查看当前已定义的函数#declare -F
查看当前已定义的函数定义#declare -f
查看当前已定义的函数名#declare -f func_name
查看当前已定义的函数名定义#declare -F func_name
trap信号捕捉
trap '触发指令' 信号 #收到信号执行触发指令
trap '' 信号 #忽略信号操作
trap '-' 信号 #恢复信号
trap -p #列出自定义信号
trap -l #列出所有信号
trap finish exit #退出前执行finshi函数
mktemp临时文件
mktemp [OPTION] ...[TEMPLATE]
说明TEMPLATE: filenameXXX X最少三个
-d #创建临时目录
-p DIR#指明临时文件存放的目录
例
[root@centos8-node1 tmp]# mktemp aaXXXXXXXXXXXXXXXXX
aanPRumSjdFiq8BUfNQ
[root@centos8-node1 tmp]# temp_file=`mktemp testXXXX.log`;echo $temp_file
testvz20.log
expect非交互式
spawn ssh 192.168.1.2
expect "password"
send "yes\n"
mkpasswd 随机口令
[root@cenots8 Linux]# mkpasswd
j97b(erRH
mkpasswd -l 10 -d 3 -C 3 -c 3 #十位数 三个数字+三个大写+三个小写
数组
数组 array 从0开始
一段连续的内存空间
声明数组#declare -a aa
1)定义数组
[root@111 ~]# aa=(192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4)
[root@111 ~]# bb[1]=tom
[root@111 ~]# bb[2]=jack
[root@111 ~]# bb[3]=xiaowang
2)调用数组的值
[root@111 ~]# echo ${aa[2]}
192.168.1.3
[root@111 ~]# echo ${aa[1]}
192.168.1.2
[root@111 ~]# echo ${aa[0]}
192.168.1.1
[root@111 ~]# echo ${bb[*]}
sb tom jack xiaowang
[root@111 ~]# echo ${bb[@]}
sb tom jack xiaowang
3)获取数组的长度
[root@111 ~]# echo ${#aa[2]}
11
[root@111 ~]# echo ${#aa[*]}
4
[root@111 ~]# echo ${#aa[@]}
4
[root@pxe7 shell]# aa=(1 2 3 4 5 6 78 9)
[root@pxe7 shell]# echo $aa
1
[root@pxe7 shell]# echo ${aa[2]}
3
[root@pxe7 shell]# echo ${aa[1]}
2
[root@pxe7 shell]# echo ${aa[@]}
1 2 3 4 5 6 78 9
[root@pxe7 shell]# echo ${aa[*]}
1 2 3 4 5 6 78 9
#!/bin/bash
#
aa=(10 2515 1515 489465 12313215 12312313 116516513132)
max=${aa[0]}
cc=${#aa[*]}
let bb=$cc-1
for i in `seq $bb`;do
if [ "$max" -lt "${aa[$i]}" ];then
max=${aa[$i]}
fi
done
echo $max
"bidui" 12L, 207C written
[root@111 ~]# bash bidui
116516513132
#
[root@rocky ~]# b=({1..10}) #数组赋值
[root@rocky ~]# echo ${b[@]}
1 2 3 4 5 6 7 8 9 10
#
[root@rocky ~]# read -a che #数组赋值
audi bmw benz
[root@rocky ~]# echo ${che[@]}
audi bmw benz
#
定义关联数组 declare -A
[root@rocky ~]# declare -A qq
[root@rocky ~]# qq[name]=wang
[root@rocky ~]# qq[age]=18
[root@rocky ~]# qq[xingbie]=nan
[root@rocky ~]# echo ${qq[@]}
nan wang 18
[root@rocky ~]# echo ${qq[name]}
wang
#
数组添加值
[root@rocky ~]# aa=({1..5})
[root@rocky ~]# echo ${aa[@]}
1 2 3 4 5
[root@rocky ~]# echo ${#aa[@]}
5
[root@rocky ~]# aa[5]=6 #也可以用aa[${#aa[@]]=6
[root@rocky ~]# echo ${aa[@]}
1 2 3 4 5 6
字符切片
1.${#变量名}
作用:返回字符串的长度
abc=“1234”
echo ${#abc}
4
2.${变量名:offset:length}
作用:截取字符串,length指定截取的长度,默认从0开始
foo="abcdefg"
echo ${foo:3:2} //从下标为3的字符串开始截取,共截取2个
de
echo ${foo:3} //从下标为3的字符串开始截取到最后的字符
defg
echo ${foo: -3} //倒数取法
efg
echo ${foo: -3:2} //倒数取3位取2个
ef
echo ${foo:2:-2} //取中间
cde
3. ${变量名#pattern} ${变量名##pattern}
parttern:模式,通配符表达式
作用:清除字符串中符合pattern的字符
foo="file.txt.zip"
echo ${foo#*.} //一个#号代表从左往右清除最短的匹配
txt.zip
echo ${foo##*.} //两个#号代表从左往右清除最长的匹配
zip
4. ${变量名%pattern} ${变量名%%pattern}
作用:清除字符串中符合pattern的字符
foo="file.txt.zip"
echo ${foo%.*} //一个#号代表从右往左清除最短的匹配
file.txt
echo ${foo%%.*} //两个#号代表从右往左清除最长的匹配
file
例:
[root@pxe7 shell]# foo="123.456.789"
[root@pxe7 shell]# echo $foo
123.456.789
[root@pxe7 shell]# echo ${foo:2:4}
3.45
[root@pxe7 shell]# echo ${foo:2:2}
3.
[root@pxe7 shell]# echo ${#foo}
11
[root@pxe7 shell]# echo ${foo%*.}
123.456.789
[root@pxe7 shell]# echo ${foo%%*.}
123.456.789
[root@pxe7 shell]# echo ${foo#*.}
456.789
[root@pxe7 shell]# echo ${foo##*.}
789
[root@pxe7 shell]# echo ${foo%.*}
123.456
[root@pxe7 shell]# echo ${foo%%.*}
123
##########################################################################
5. ${变量名/old/new} ${变量名//old/new}
作用:替换
echo ${foo/t/T} /从左往右替换第一个t
file.Txt.zip
echo ${foo//t/T} 替换所有t
file.TxT.zip
echo ${foo/#t/T} 替换第一个
echo ${foo/%t/T} 替换最后一个
例:
[root@pxe7 shell]# echo $foo
123.456.789
[root@pxe7 shell]# echo ${foo/123/qqq}
##################################################################################
qqq.456.789
6.大小写转换
[root@111 ~]# foo="ABcd"
[root@111 ~]# echo ${foo,} 第一个字母变小写
aBcd
[root@111 ~]# echo ${foo,,} 所有变小写
abcd
[root@111 ~]# echo ${foo^} 第一个字母变大写
ABcd
[root@111 ~]# echo ${foo^^} 所有变大写
ABCD
##################################################################################
[root@rocky nginx-1.12.2]# echo ${!n*} #显示所有n开头的变量
nginx nginxdir