shell脚本---实际上手

shell脚本—实际上手

符号

双引号" ":允许通过$符号引用其他变量值

单引号' ':禁止引用其他变量值,$视为普通字符、`..`和$(..)作用相同

"$name"  弱引用,其中的变量引用会被替换为变量值
'$name'  强引用,其中的变量引用不会被替换为变量值,而保持原字符串

反撇号` `:命令替换,提取命令执行后的输出结果

感叹号!:表示历史替换
!!:上一个命令(会执行)
!n:表示历史中的第n个命令

小括号():在正则表达式中匹配并记住匹配的子串;在Shell脚本中创建子shell或定义数组

中括号[]:在正则表达式中定义字符集,匹配方括号中的任意一个字符;在Shell脚本中,用于数组索引和条件测试

双小括号(()):算术扩展和算术运算

双中括号[[]]:条件测试

—read 获取输入内容

-p prompt:指定提示符,用于提示用户输入数据

-a array:将输入数据存储到一个数组中。

方法-:
read -p "提示信息" 变量名
echo$变量名

方法二:
echo -n "提示信息”
read 变量名
echo$变量名

read -a 		#数组输入

运算

## 整数变量的运算

格式:expr 变量1 运算符 变量2 [运算符 变量3]

运算符
+ 加法
- 减法
\* 乘法
/ 除法
% 取余

常用的运算表达式:
i=$(expr 12 \* 5)
i=$((12*5))
i=$[12*5]  #这种用法已弃用
let i=12*5

bc  将数学表达式计算结果输出到标准输出或保存到文件中

## 非整数运算

scale:保留几位小数

-a:&&
-o:||

常用的操作符:
-eq:等于		==
-ne:不等于	   !=
-gt:大于		\>
-lt:小于		\<
-le:小于等于   <=
-ge:大于等于   >=

$> /dev/null 放入null垃圾桶===不在前台显示

条件测试操作

Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0(真true)时表示成功,返回值为非0值(假false)时表示失败或异常。

—test

对特定条件进行测试,并根据返回值来判断条件是否成立

格式一:test 条件表达式

格式二:[ 条件表达式 ]			#方括号“[”或“]”与条件表达式之间需要至少一个空格进行分隔

—文件测试

格式:[ 操作符 文件或目录 ]

常用的操作符:
-e:测试目录或文件是否存在(Exist)。
-d:测试是否为目录(Directory)。
-f:测试是否为文件(File)。
-r:测试当前用户是否有权限读取(Read)。
-w:测试当前用户是否有权限写入(Write)。
-x:测试是否设置有可执行(Excute)权限。

—字符串比较

格式1:
[  字符串1  =  字符串2 ] 或 [  字符串1  ==  字符串2 ] 
[  字符串1  !=  字符串2 ]

格式2:
[  -z  字符串 ]		#检查字符串是否为空(Zero),对于未定义或赋予空值的变量将视为空串
[  -n  字符串 ]		#检查是否有字符串存在

—逻辑测试

格式1:[  表达式1  ]  操作符  [  表达式2  ]  
格式2:命令1  操作符  命令2

常用的操作符:
-a或&& :逻辑与,“而且”的意思,前后条件需都成立
-o或|| :逻辑或,“或者”的意思,只需前后条件中一个成立
! :逻辑否

常用转义字符

前置
echo -n 表示不换行输出
echo -e 输出转义字符,将转义后的内容输出到屏幕上  echo -ne 
只有加了-e才能执行下面的转义符

常用的转义字符   
\b 转义后相当于按退格键(backspace),但前提是"\b"后面存在字符;"\b"表示删除前一个字符,"\b\b"表示删除前两个字符。

\c 不换行输出,在"\c"后面不存在字符的情况下,作用相当于 echo -n; 但是当"\c"后面仍然存在字符时,"\c"后面的字符将不会被输出。

\n 换行,被输出的字符从"\n"处开始另起一行。 
 
\f 换行,但是换行后的新行的开头位置连接着上一行的行尾;

\v 与\f相同;

\t 转以后表示插入tab,即横向制表符;

\r 光标移至行首,但不换行,相当于使用"\r"以后的字符覆盖"\r"之前同等长度的字符;但是当"\r"后面不存在任何字符时,"\r"前面的字符不会被覆盖

\\ 表示插入"\"本身;

条件

if语句

单分支 if 语句
if 条件测试操作

	then
	命令序列

fi
双分支 if 语句
if 条件测试操作

	then
	命令序列 1

	else
	命令序列 2

fi
多分支 if 语句
if 条件测试操作 1

	then
	命令序列 1

	elif 条件测试操作 2

	then
	命令序列 2

	[else]
	[命令序列 3]

fi

case 语句

case 变量值 in

模式 1)
命令序列 1
;;

模式 2)
命令序列 2
;;

……
*)
默认命令序列

esac

注意特点
case 行尾必须为单词“in”,每一模式必须以右括号“)”结束。
双分号“;;”表示命令序列的结束。

模式字符串中,可以用方括号表示一个连续的范围,如“[0-9]”;还可以用竖杠符号“|”表示或,如“A|B”。

“*)”表示默认模式,其中的*相当于通配符。

循环

for
格式一
for i $()
do

done

格式二  (类C语言格式)
for ((i=0;i>=5;i++))
do

done

跳出循环
continue 在循环内部跳过本次循环并继续下一次循环
continue 2 跳过两层循环,并继续下一次循环

break 直接结束此次循环
break n 结束n次循环
====================
# 死循环(无限循环)
for ((;;))
do

done
while
while   [ 判断条件]  
do       

执行动作

done
====================
# 死循环(无限循环)
第一种
while  [1  -eq  1]   判断条件写一个永久为真的条件 
do  

done

第二种
while  true        直接写判断条件为真
   do    

   done

第三种
while :         判断条件为冒号也表示死循环
   do     

   done
until
until  [ 条件测试操作 ]
do
	判断式/命令序列
done

function 函数

function 函数名() {

主体

return 返回值

}

函数返回值
return表示退出函数并返回一个退出值,脚本中可以用 $? 变量显示该值

使用原则:
1、函数一结束就取回返回值,因为 $? 变量只返回执行的最后一条命令的退出状态码
2、退出状态码必须是0-255,超出时值将为除以256取余 exit 0

数组

格式一
数组名=(value0 valuel value2 …)
例:
arr=(30  20  10  60)   #数组中的元素值
其中:
30为索引0
20为索引1
10为索引2
60为索引3
以此类推

格式二
数组名=( [0]=value [1]=value [2]=value …)
例:
arr=([0]=1 [1]=2 [2]=3)

格式三
列表名=“value0 valuel value2 …”
数组名=($列表名)
例:
list="1 2 3 4"
arr=($list)

格式四
数组名[0]=“value0”
数组名[1]=“value1”
数组名[2]=“value2”
例:
arr3[0]="1
arr3[0]="2
arr3[0]="3

数组中总共多少个元素====长度
arr1=(1 2 3 4 5)
echo ${#arr1[*]}
-------5

读取某下标赋值
arr1=(1 2 3 4 5)
echo ${arr1[0]}
-------1
echo ${arr1[3]}
-------4

数组遍历
#!/bin/bash
arr5=(1 2 3 4 5)
for i in ${arr5[*]}   或  for i in ${arr5[@]}     #使用*或者@表示都可以
do
  echo $i
done
-----1
-----2
-----3
-----4
-----5

数组切片
取数组中的某一段的元素的值
${数组名[@或*]}:起始位置(起始索引):长度
arr1=(1 2 3 4 5)
echo ${arr1[*]:0:2}
-------1 2
echo ${arr1[*]:2:2}
--------3 4

数组替换
临时替换或者永久替换
$(数组名[@或*]/查找字符/替换字符}
arr1=(1 2 3 4 5)

#临时替换
echo ${arr1[*]/4/66}   #将数组arr1中的元素4替换为66
-----1 2 3 66 5
echo ${arr1[*]}  #原来的数组中的元素的值并不会改变
--------1 2 3 4 5 

#永久替换
方法一:可通过重新赋值实现
arr1=(${arr1[*]/4/66})
echo ${arr1[*]}
--------1 2 3 66 5

方法二:直接修改
arr1[3]=44
echo ${arr1[*]}
--------1 2 3 44 5 6

删除数组
使用unset删除数组
unset arr1
echo ${arr1[*]}

删除数组中的某个索引对应的元素的值
arr1=(1 2 3 4 5)
echo ${arr1[*]}
-------1 2 3 4 5
unset arr1[2]       #删除索引2的对应的元素值
echo ${arr1[*]}
--------1 2 4 5

追加数组中的元素
方法一:
arr1=(1 2 3 4 5)
echo ${arr1[*]}
-------1 2 3 4 5    #这是原始的数组中的各元素的值,一直到索引4结束
arr1[5]=6          #此时追加数组索引5对应的元素值为6
echo ${arr1[*]}
--------1 2 3 4 5 6       #发现数组的索引5位置上的元素已经追加成功

方法二:
arr1[${#arr1[*]}]=7      
#当数组的元素非常多的时候,可以直接使用数组的长度作为自己将要追加的索引的值,这样就可以直接追加元素了。
因为原始数组的索引是从0开始的,所以用长度减去1就是原始数组的最后的以为索引值了,
那么自己将要添加的值应该是原始索引值的后一位,那显然就等于数组的长度值了。
echo ${arr1[*]} 
-------1 2 3 4 5 6 7

方法三:
arr1=(1 2 3 4 5)
echo ${arr1[*]}
-------1 2 3 4 5
arr1=("${arr1[@]}" 6 7)
echo ${arr1[*]}
----------1 2 3 4 5 6 7

双引号不能省略,否则,当数组arr1中存在包含空格的元素时会按空格将元素拆分成多个。
不能将“@“替换为“*”,如果替换为"*",
不加双引号时与"@"的表现一致,加双引号时,会将数组arr1中的所有元素作为一个元素添加到数组中。
可以简单的理解为:用*号是作为一个整体,而用@还是单个的个体。

$*、$@不加双引号时表现一致;加双引号时,$*会将所有参数作为一个整体。

"$*" 为 “1 2 3” (作为一个整体使用)
"$@" 为“1” “2” “3” (分别作为单个的个体使用)
"$#" 为3 (表示参数的数量,也可以叫做长度)

方法四:
arr1=(1 2 3 4 5)
echo ${arr1[*]}
------1 2 3 4 5
arr1+=(11 22)   #追加,待添加元素必须用“()"包围起来,并且多个元素用空格分隔
echo ${arr1[*]}
------1 2 3 4 5 11 22

调试

set -x 开启调试模式
set +x 关闭调试模式

脚本调试debug

bash -n 脚本名称--------检查语法错误

bash -x 脚本名称--------检查逻辑错误

免交互

EOF—标记

语法格式:
命令  <<标记
...	
内容			#标记之间是传入内容
...
标记

注意事项:
标记可以使用任意合法字符(通常为EOF)
结尾的标记一定要顶格写,前面不能有任何字符
结尾的标记后面也不能有任何字符(包括空格)
开头标记前后的空格会被省略掉

例:
通过 read 命令接收输入并打印,输入值是两个 EOF 标记之间的部分,作为变量 i 的值
read i <<EOF
>Hi
>EOF
echo $i

通过 passwd 给用户设置密码
passwd lisi <<EOF
>abc1234 			#这两行是输入的密码和确认密码
>abc1234
>EOF

cat <<EOF>test.txt
> hello world
> i im zhangsan
> EOF
[root@localhost ~]#cat test.txt

tee命令重定向输出加标准输出  
[root@localhost ~]#tee test2.txt <<EOF
> this is tee test
> EOF
this is tee test
[root@localhost ~]#cat test2.txt
#tee命令有标准输出的作用,可以直接重定向输入到文件中

在写入文件时会先将变量替换成实际值,再结合 cat 命令完成写入
#!/bin/bash
file="test1.txt"
i="school"
cat > $file <<EOF
I am going to $i
EOF
cat EOF1.txt

整体赋值给变量,然后通过 echo 命令将变量值打印出来
#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<EOF			 
This is Line 1.
Today is Monday.
$var
EOF
)
echo "$myvar"

关闭变量替换的功能,按照字符原本的样子输出,不做任何修改或替换
#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<'EOF'			          #对标记加单引号,即可关闭变量替换			 
This is Line 1.
Today is Monday.
$var
EOF
)

echo $myvar                           #这是会输出什么呢?就是$var

去掉每行之前的 TAB 字符
#在标记前加“-”,即可抑制各行首TAB		 

cat <<-'EOF'
                KY27
   ky28
EOF
#注意一点,用空格无效

Expect

#!/usr/bin/expect expect 脚本中首先引入文件,表明使用的是哪一个 shell。

常见转义字符

\n:表示换行符。
\t:表示制表符。
\r:表示回车符。
\b:表示退格符。

spawn

spawn 后面通常跟一个Linux执行命令,表示开启一个会话、启动进程,并跟踪后续交互信息。
spawn  命令

expect

判断上次输出结果中是否包含指定的字符串
只能捕捉由spawn启动的进程的输出

send

模拟用户的输入
该命令不能自动回车换行,一般要加\r(回车)或者\n

组合

格式一
expect "关键字" {send "用户输入\r"}    #\r是回车

格式二
expect "关键字"	
send "用户输入\r"

格式三
expect					#只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
{
"关键字1" {send "用户输入\r"}
"关键字2" {send "用户输入\r"}
"关键字3" {send "用户输入\r"}
}

结束符

expect eof    表示交互结束,等待执行结束,退回到原用户,与spawn对应

interact  执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端而不会退回到原终端

interact后的命令不起作用
expect eof 与 interact 只能二选一

附加

set
expect 默认的超时时间是 10 秒
若不限制超时时间则应设置为-1
例:set timeout 5
exp_continue
附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项
允许 expect 继续向下执行指令
分号;隔开

注意:使用exp_continue时,如果跟踪像 passwd 这样的输入密码后就结束进程的命令
expect{}外不要再加上expect eof
因为spawn进程结束后会默认向expect发送eof,会导致后面的 expect eof 执行报错
send_user
send_user 表示回显命令,相当于 echo打印的功能
接收参数
expect 脚本可以接受从bash命令行传递的参数
使用[lindex $argv n]获得。其中n从0开始,分别表示第一个,第二个,第三个....参数

类似与位置变量,用法相同
例:
set hostname [lindex $argv 0]   	相当于 hostname=$1
set password [lindex $argv 1]		相当于 password=$2

注意:expect脚本不能通过bash、source、. 
来执行(因为这三种方式是调用shell解释器),只能通过绝对路径或相对路径来执行。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值