for 变量名 in 列表;do
循环体
done
列表生成方式有多重,详情可查看其他博客所总结。
双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作
I=10
((I++))
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
while CONDITION; do
循环体
done
进入条件:CONDITION为true
退出条件:CONDITION为false
until CONDITION; do
循环体
done
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done
用于循环体中
break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done
shift [n]
用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。 while 循环遍历位置参量列表时,常用到 shift
例如:
./doit.sh a b c d e f g h
./shfit.sh a b c d e f g h
示例:doit.sh
#!/bin/bash
# Name: doit.sh
# Purpose: shift through command line arguments
# Usage: doit.sh [args]
while [ $# -gt 0 ] # or while (( $# > 0 ))
do
echo $*
shift
done
示例:shift.sh
#!/bin/bash
#step through all the positional parameters
until [ -z "$1" ]
do
echo "$1"
shift
done
echo
while true; do
循环体
done
until false; do
循环体
Done
遍历文件每一行这个写法很实用,参考自己写的创建用户的脚本读入每一行的命令就知道为何实用了(因为它只把换行符当做分隔符,而不把空格当做分隔符,每一行当做一个长字符串存入变量中)
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
PS3="Please input a number:"
select variable in list
do
循环体命令
done
PS3="please input a number:"
select menu in backup clean config start stop status restart quit;do
case $menu in
*)
echo $REPLY
echo $menu;;
esac
done
函数由两部分组成:函数名和函数体
help function
语法一:
f_name (){
...函数体...
}
语法二:
function f_name {
...函数体...
}
语法三:
function f_name () {
...函数体...
}
使子进程也可使用
声明:export -f function_name
查看:export -f 或 declare -xf
fork×××是一种恶意程序,它的内部是一个不断在fork进程的无限循环,实质是一个简单的递归程序。由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源
func_factorial(){
local input=$1
if func_ispositint $input ;then
[ $input -gt 1 ] && echo $[`func_factorial $[input-1]`*input] || echo 1
else
echo -e "Please input a positive integer"
return 1
fi
}
注意下面这两个命令,它俩显示是已经加载入内存中正在被引用的函数
action string true :它就会显示正确结果 action string false : 它就会显示错误结果
注意因为函数是在当前shell中运行,因此它的变量会影响当前脚本或者shell中的变量结果(也就是两个变量名字相同会造成变量污染),因此 函数中的变量一般都定义为 local variable=赋值;
三个返回:return 返回出函数;break,continue 返回出循环;exit 返回出shell(脚本) ;
函数类似脚本后面也可以跟参数,用法一模一样。注意$*和$@的区别,加上双引号引用此参数传递到子函数或者子脚本中,前者代表一整个字符串作为一个参数,后者代表分别作为一个一个参数。不加上双引号没区别,这也是因为不加双引号会把里面的空格作为分隔符。
#!/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 关联数组:必须先声明才可以使用,如果先使用了,必须unset之后再重新声明才可以使用
注意:两者不可相互转换
17:47[root@centos7 /etc/sysconfig/network-scripts]# abc=12334
17:54[root@centos7 /etc/sysconfig/network-scripts]# echo ${abc[0]}
12334
17:54[root@centos7 /etc/sysconfig/network-scripts]# echo ${abc}
12334
17:54[root@centos7 /etc/sysconfig/network-scripts]# echo ${#abc}
5
17:57[root@centos7 /data/scriptest]# array=([1]=12wad [5]=ff [6]=cvv [8]=1wd234)
17:57[root@centos7 /data/scriptest]# echo $array
17:57[root@centos7 /data/scriptest]# echo ${array[0]}
17:58[root@centos7 /data/scriptest]# echo ${array[1]}
12wad
17:58[root@centos7 /data/scriptest]# echo ${#array[1]} :第一个元素的长度
5
17:58[root@centos7 /data/scriptest]# echo ${#array[*]} :数组总长度,稀疏数组只看有几个元素就是几
4
17:58[root@centos7 /data/scriptest]# echo ${array[1]:2:3} :第一个元素内容切片
wad
17:58[root@centos7 /data/scriptest]# echo ${array[*]}
12wad ff cvv 1wd234
20:00[root@centos7 /data/scriptest]# echo ${array[*]:2:2} :取不同的数组元素,注意和元素内容切片的区分
ff cvv
20:00[root@centos7 /data/scriptest]# echo ${array[*]:2:3}
ff cvv 1wd234
(1) 一次只赋值一个元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
(2) 一次赋值全部元素(注意尽量要加上引号,虽然空格也可以作为分隔符)
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只赋值特定元素
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
(4) 交互式数组值对赋值(注意有一个-a的选项)
read -a ARRAY
num=({1..10}) :1到10赋值给num[0]到num[9]
file=(*.sh) :当前目录中sh后缀的文件名赋值给file数组
19:40[root@centos7 /data]# testarray[2]=12
19:40[root@centos7 /data]# testarray[5]=1234
19:40[root@centos7 /data]# echo ${testarray[2]}
12
19:40[root@centos7 /data]# declare -a
declare -a testarray=‘( [2]="12" [5]="1234")‘
19:40[root@centos7 /data]# testarray=( [1]=wade [3]=waef )
19:40[root@centos7 /data]# echo ${testarray[2]}
19:40[root@centos7 /data]# declare -a
declare -a testarray=‘([1]="wade" [3]="waef")‘
上面会覆盖,然后继续,下面的不会覆盖:
19:40[root@centos7 /data]# testarray[2]=12
19:44[root@centos7 /data]# testarray[5]=1234
19:44[root@centos7 /data]# declare -a
declare -a testarray=‘([1]="wade" [2]="12" [3]="waef" [5]="1234")‘
#!/bin/bash
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[$i]} && max=${nums[$i]}&& continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]}
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo “All numbers are ${nums[*]}”
echo Max is $max
echo Min is $min
#!/bin/bash
#
declare -a files
files=(/var/log/*.log)
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d‘ ‘ -f1)
fi
done
echo "Lines: $lines."
${var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
${var%word*}:其中word可以是指定的任意字符
功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符
${var^^}:把var中的所有小写字母转换为大写
${var,,}:把var中的所有大写字母转换为小写
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数 :或者export
-l 声明变量为小写字母 declare –l var=UPPER :即使输入大写字母,也会变成小写字母,下同相反
-u 声明变量为大写字母 declare –u var=lower
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
间接变量引用是指通过variable1获得变量值value的行为
variable1=variable2
variable2=value
mktemp命令:创建并显示临时文件,可避免冲突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出现三个
install [OPTION]... [-T] SOURCE DEST 单文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...创建空目录
expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率
它执行的时候会捕获屏幕上出现的关键字,然后根据出现的key来自动提交(输入)内容
示例
#!/usr/bin/expect
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "www.123\n" }
}
expect eof
#!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "www.123\n" }
}
interact
#expect eof
示例:变量,变量设置和赋值用set,后面不加等号
#!/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
示例:位置参数:变量从0开始而不是shell中的从1开始
#!/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 www
示例:执行多个命令
#!/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 www |passwd --stdin haha\n" }
send "exit\n"
expect eof
#./ssh4.exp 192.168.8.100 root www
示例:shell脚本调用expect,就是用多行重定向的方式来使用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 www |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
#./ssh5.sh 192.168.8.100 root www
19.Shell编程进阶,数组,字符串(for,select,while read line,dec
原文:https://blog.51cto.com/14228129/2379087