本章概要:循环控制(for/while/until/select)、函数、数组、declare、eval、expect等。
#格式1
for 变量名 in 列表 ; do
循环体
done
#格式2
for ((i=1;i<j;i++))
do
循环体
done
{1..100[..步进]}、$(seq [start [stop]] end)
$@、$*
#当CONDITION为真时。循环
while CONDITION ; do
循环体
done
#无限循环
while :
do
statement
done
while read line ; do
statement
done < /path/file
直到CONDITION为真时。退出循环
#直到CONDITION为真时。退出循环
until CONDITION ; do
循环体
done
select var in list
do
statement
done
N层循环是指循环嵌套的层
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断
break [N]:提前结束第N层循环,最内层为第1层
参量列表是指:脚本输入的参数
shift [N]:用于将参量列表 list 左移指定次数,缺省为左移一次
示例
[root.CentOS 7] ➤ cat break.sh
while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done
[root.CentOS 7] ➤ bash break.sh 1 2 3 45 6 7 8 9 0
1 2 3 45 6 7 8 9 0
2 3 45 6 7 8 9 0
3 45 6 7 8 9 0
45 6 7 8 9 0
6 7 8 9 0
7 8 9 0
8 9 0
9 0
0
#语法1(推荐)
fname (){
函数体
}
#语法2
function fname{
函数体
}
#语法3
function fname() {
函数体
}
> cat function.main
#!/bin/bash
findit(){
echo hello
}
. function.main
或
source function.main
unset function_name
环境函数
使子进程也可使用
声明:export -f function_name
查看:export -f 或 declare -xf
函数参数
函数也可以使用$1,$2,$@,$*,$#
函数局部变量:local NAME=VALUE
函数递归
#!/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
#函数调用
fact $1
信号可以用"kill -l"查看可用信号
#!/bin/bash
trap 'echo “signal:SIGINT"' int
trap -p
for((i=0;i<=10;i++))
do
sleep 1
echo $i
done
trap '' int
trap -p
for((i=11;i<=20;i++))
do
sleep 1
echo $i
done
trap '-' int
trap -p
for((i=21;i<=30;i++))
do
sleep 1
echo $i
done
declare -a ARRAY_NAME
declare -A ARRAY_NAME 关联数组
ARRAY_NAME[INDEX]=VALUE
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
read -a ARRAY
declare -a
${ARRAY_NAME[INDEX]}
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
unset ARRAY[INDEX]
unset ARRAY
${ARRAY[@]:offset:number}
ARRAY[${#ARRAY[*]}]=value
declare -A ARRAY_NAME
${#var}
: 返回字符串变量var的长度${var:offset}
: 返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)${var:offset:number}
:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分${var: -length}
:取字符串的最右侧几个字符${var:offset:-length}
:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容${var: -length:-offset}
:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容${var#*word}
:其中word可以是指定的任意字符${var##*word}
:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容file=“var/log/messages”
${file#*/}: log/messages
${file##*/}: messages
${var%word*}
:其中word可以是指定的任意字符${var%%word*}
:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符url=http://www.magedu.com:80
${url##*:} 80
${url%%:*} http
${var/pattern/substr}
:查找var,第一次被pattern所匹配,以substr替换之${var//pattern/substr}
: 查找var,所有能被pattern所匹配,以substr替换之${var/#pattern/substr}
:查找var,行首被pattern所匹配,以substr替换之${var/%pattern/substr}
:查找var,行尾被pattern所匹配,以substr替换之${var/pattern}
# 删除var第一次被pattern匹配的${var//pattern}
# 删除var所有被pattern匹配的${var/#pattern}
# 删除var所有以pattern为行首匹配的${var/%pattern}
# 删除var所有以pattern为行尾所匹配的${var^^}
:把var中的所有小写字母转换为大写${var,,}
:把var中的所有大写字母转换为小写变量配置方式 | 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} |
var=expr str=expr |
str不变 var= |
str不变 var=$str |
var=${str:=expr} |
var=str=expr | var=str=expr | str不变 var=$str |
var=${str?expr} |
expr输出到stderr | var= | var=$str |
var=${str:?expr} |
expr输出到stderr | expr输出到stderr | var=$str |
Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
[OPTION] | 意义 |
---|---|
-r |
声明或显示只读变量 |
-i |
将变量定义为整型数 |
-a |
将变量定义为数组 |
-A |
将变量定义为关联数组 |
-f |
显示已定义的所有函数名及其内容 |
-F |
仅显示已定义的所有函数名 |
-x |
声明或显示环境变量和函数 |
-l |
声明变量为小写字母 declare –l var=UPPER |
-u |
声明变量为大写字母 declare –u var=lower |
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
+示例:
[root@server ~]# CMD=whoami
[root@server ~]# echo $CMD
whoami
[root@server ~]# eval $CMD
root
[root@server ~]# n=10
[root@server ~]# echo {0..$n}
{0..10}
[root@server ~]# eval echo {0..$n}
0 1 2 3 4 5 6 7 8 9 10
eval var1=\$$var2
var1=${!var2}
[root@localhost ~]$var1=var2
[root@localhost ~]$var2=mage
[root@localhost ~]$echo $var1
var2
[root@localhost ~]$echo \$$var1
$var2
[root@localhost ~]$eval echo \$$var1
mage
[root@localhost ~]$echo ${!var1}
mage
创建并显示临时文件,可避免冲突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX(X是随机数)
[OPTION] | 意义 |
---|---|
-d | 创建临时目录 |
-p DIR或–tmpdir=DIR | 指明临时文件所存放目录位置 |
mktemp /tmp/testXXX
tmpdir=`mktemp –d /tmp/testdirXXX`
mktemp --tmpdir=/testdir testXXXXXX
复制文件并设置属性
install [OPTION]... SOURCE... DIRECTORY
[OPTION] | 意义 |
---|---|
-m MODE | 默认755 |
-o OWNER | 所有者 |
-g GROUP | 所属组 |
-d DIR | 创建空目录 |
#复制文件file1,2,3到dir
install -t dir file1 file2 file3
#复制文件srcfile到desfile并设置属性
install -m 700 -o wang -g admins srcfile desfile
#创建目录/testdir/installdir并设置属性
install –m 770 –d /testdir/installdir
expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率
expect 语法:
expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
选项:
-c
:从命令行执行expect脚本,默认expect是交互地执行的
示例:expect -c 'expect “\n” {send “pressed enter\n”}
-d
:可以输出输出调试信息
示例:expect -d ssh.exp
命令
expect中相关命令
spawn 启动新的进程
send 用于向进程发送字符串
expect 从进程接收字符串
interact 允许用户交互
exp_continue 匹配多个字符串在执行动作后加此命令
单一分支模式语法:
expect “hi” {send “You said hi\n"}
匹配到hi后,会输出“you said hi”,并换行
expect "hi" { send "You said hi\n" } \
"hehe" { send "Hehe yourself\n" } \
"bye" { send "Good bye\n" }
#匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:
expect {
"hi" { send "You said hi\n"}
"hehe" { send "Hehe yourself\n"}
"bye" { send " Good bye\n"}
}
#!/usr/bin/expect
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
expect eof
#!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
interact
#expect eof
# 变量
#!/usr/bin/expect
set ip 192.168.8.100
set user root
set password magedu
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
# 位置参数
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#./ssh3.exp 192.168.8.100 root magedu
# 执行多个命令
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo magedu |passwd --stdin haha\n" }
send "exit\n"
expect eof
#./ssh4.exp 192.168.8.100 root magedu
# shell脚本调用expect
#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
#./ssh5.sh 192.168.8.100 root magedu
参考答案:(https://pan.baidu.com/s/1V1w5ChHGuU56akZk3MsPbQ)提取码:wjqt
用for实现
1 2 3 1 4 7
4 5 6 ===> 2 5 8
7 8 9 3 6 9