1.1 Shell脚本的概念
Shell Script,Shell脚本与Windows/Dos下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比Windows下的批处理更强大,比用其他编程程序编辑的程序效率更高,它使用了Linux/Unix下的命
令
1.2 shell脚本的发展
(1)sh :人机交互差,语言难懂。
(2)csh :c风格的sh脚本,人机交互差。
(3)ksh :人机交互好,但是语言难懂。
(4)bash:c风格代码,人机交互好。
1.3 shell脚本的简单使用
(1) 程序编写
#!/bin/bash
ls -al
(2) 程序运行
方法一:./1-test.sh
# 1.需要可执行权限
# 2.新开子终端,在子终端运行后,将结果返回给当前终
端
xy@ubuntu:~/Linux/day3$ ./1-test.sh
bash: ./1-test.sh: 权限不够
xy@ubuntu:~/Linux/day3$ chmod u+x 1-
test.sh
xy@ubuntu:~/Linux/day3$ ./1-test.sh
总用量 12
drwxrwxr-x 2 xy xy 4096 9月 27 09:44 .
drwxrwxr-x 5 xy xy 4096 9月 27 09:42 ..
-rwxrw-r-- 1 xy xy 25 9月 27 09:44 1-test.sh
法二:bash 1-test.sh (推荐)
# 1.不需要可执行权限
# 2.新开子终端,在子终端运行后,将结果返回给当
前终端
方法三:source 1-test.sh
# 1.不需要可执行权限
# 2.直接在当前终端运行
1.4 shell脚本-变量
shell脚本中的变量没有类型,变量也不需要定义,直接使用即可
(1) 赋值方式
i) 直接赋值
var=123
var=$变量名
#1.变量的值不能有空格
#2.可以直接调用变量
ii)单引号赋值
var='123 456'
#1.变量的值可以有空格
#2.不可以调用变量
iii)双引号赋值
var="123 $变量名"
#1.变量的值可以有空格
#2.可以调用变量
(2) 变量的调用
#1.不能用于调用数组 2.不能用于调用${10}以及${10}
以上的位置变量
调用方式1:$变量名
#可以调用所有类型的变量
调用方式2:${变量名}
(3)变量的输出
echo $var2
echo "var2 = $var2"
(4) 位置变量
从终端向脚本中输入值的一种方法,通过
$0,$1,$2,$3,...,${10},${11},...,${n}来获取。
#!/bin/bash
echo "$0"
echo "$1"
echo "$2"
i) c语言中的命令行参数
#include <stdio.h>
/*
*argc:命令行参数的个数
*argv: 命令行参数的内容
*
* */
int main(int argc, const char *argv[])
{
printf("argc = %d\n",argc);
for(int i =0 ; i < argc;i++)
{
printf("%s\n",argv[i]);
}
return 0;
}
1.5 shell脚本--数组
(1) 数组的特点
1.数组大小没有上限
2.数组元素和元素之间用空格隔开
3.数组用()开进行标识。
(2) shell中的通配符
#:表示计算元素的个数或者字符串的大小
@:表示所有的意思
*:表示所有的意思
#!/bin/bash
arr=(123 "hello world" 789) #()表示arr是一个
数组
echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}
echo ${arr[@]} #打印数组所有的元素
echo ${#arr[@]} #计算数组元素的个数
(3) 数组元素的修改和追加
#追加方式一:
arr=(${arr[@]} "追加的内容")
echo ${arr[@]} #打印数组所有的元素
#追加方式二:
arr[9]="追加九"
arr[8]="追加八"
echo ${arr[@]} #打印数组所有的元素
echo ${#arr[@]} #打印数组所有的元素
echo ${@} #表示所有的位置变量
echo ${#@} #计算位置变量的个数
(4) unset
清空变量的值
unset arr #清空变量arr的值
(5) readonly
将变量设置为只读
readonly arr=($@)
1.6 shell中的运算
(1) 运算方式
方式一:(())
方式二:$[]
方式三:expr
(2) shell中的运算符
shell中的运算符
算术运算符 说明/含义
+ - 加法(或正号)、减法(或负号)
* / % 乘法、除法、取余(取模)
** 幂运算
++ -- 自增和自减,可以放在变量的前面也可以放在变量的后面
! && || 逻辑非(取反)、逻辑与(and)、逻辑或(or)
< <= > >= 比较符号(小于、小于等于、大于、大于等于)
== != = 比较符号(相等、不相等;对于字符串,= 也可以表示相当于)
<< >> 向左移位、向右移位
~ | & ^ 按位取反、按位或、按位与、按位异或
= += -= *= /= %= 赋值运算符,例如 a+=1 相
当于 a=a+1,a-=1 相当于 a=a-1
(3) (())
特点:
1.风格类似于c,(())内可以有空格,也可以没有,可以有
$,也可以不写$
2.可以做复杂的运算
i)简单使用
#!/bin/bash
num1='123'
num2=456
#sum=$num1+$num2
#sum=$((num1 + num2))
((sum=num1 + num2))
echo "sum = $sum"
ii) 计算累加1~100的和
#!/bin/bash
sum=0 #统计和
for((i=1;i <=100;i++))
do
((sum += i))
done
echo "sum = $sum"
iii) 逗号表达式
#!/bin/bash
var1=123
var2=456
sum=$((var1++,++var2,++var1,3**5))
echo "sum = $sum"
echo "var1 = $var1"
echo "var2 = $var2"
(4) $[ ]
特点:
1.$[]内部可以有空格,也可以不用$符号调用变量
2.$[]计算的结果必须要有变量来承接或者输出其结果
3.$[]内部不能做复杂的计算(循环等)
#!/bin/bash
num1=123
num2=123
#$[num1+num2] # $[]不能单独计算
ret=$[num1 + num2] #1.用一个变量承接结果
echo "ret = $ret"
echo $[num1 + num2] #2.输出$[]计算的结果
#for $[i = 0 ; i < 100;i++] #3.不能做复杂的运算
#do
# echo "hello"
#done
echo $[num1++,++num2,3**5]
(5) expr
var1=12
var2=13
expr $var1 + $var2
[1]expr在运算完之后结果会自动显示
[2]expr在使用变量的时候,变量前一定要有$符号
[3]运算符前后要加空格,如果不加空格就会出错
sum=`expr $var1 + $var2`
echo $sum
[4]如果要将expr的运行的结果赋值给新的变量,需要使用命令置换。
mul=`expr 6 \* 3`
[5]expr在进行*运算的时候如果不使用转义符号时,它认为是通配符号,不能进行幂运算。
注:如果要将一个命令执行的结果赋值给一个变量使用命令置换符号
var1=`ls`
var1=$(ls)
[6]使用expr求字符串的长度
expr length $var2
注:var2变量中不能有空格,如果有空格就会出现语法的错误。
[7]使用expr在源字符串中子字符串中任意一个字符第一次出现的位置,
如果子串中没有字符与字符串中字符匹配,则返回0
expr index $var1 "wh" #1
[8]提取字符串
#从起始位置开始,向后提取n个元素
expr substr $var 起始位置(m) 提取元素个数(n)
[9]字符串的匹配
expr match $var1 "www.h"
从左侧第一个字符开始进行匹配,如果匹配成功了返回匹配成功的字符的个数,否则返回0。如果有任意一个匹配不上就返回0.
#!/bin/bash
var1=123
var2=456
#expr $var1 + $var2
sum=`expr $var1 + $var2` #将expr执行的结果赋
值给新的变量,需要使用命令置换
echo $sum
#sum=`ls` #将ls当作命令来执行,将ls执行的结果赋
值给sum
#echo "$sum"
#sum=(`ls`) #将ls当作命令来执行,将ls执行的结
果赋值给sum
#echo "${sum[@]}"
#!/bin/bash
num1=$1
#num1="$1 world" #变量不能有空格
expr length $num1 #表示计算num1的长度
expr index $1 "wh"
expr substr $1 2 5 #从第二个元素开始,向后提取
5个元素
expr match $1 "www.baidu.com"
1.7 shell中的注释
# 单行注释
:<<! #多行注释 (不推荐,有时会出现问题)
被注释掉的部分
!
#!/bin/bash
:<<EOF
for $[i = 0 ; i < 100;i++]
do
echo "helloworld"
done
EOF
1.8 分支语句-if
(1) 语法格式
#方式一 []前后 和 []中所有的表达式都必须要用空格隔
开
#if [ 判断条件1 ]
#方式二:if 后面所有语句都必须使用空格隔开
if test 判断条件1
then
语句块1
elif [ 判断条件2 ]
then
语句块2
else
语句块3
fi
(2) 注意事项
1.if和fi一一对应
2.每一个if语句后都需要有then
3.if后面两种写法,所有的表达式都必须使用空格隔开。
(3) if中的判断条件
i) 对数字的判断
> : -gt
< : -lt
>= : -ge
<= :-le
== :-eq
!= : -ne
ii) 逻辑运算
&& --->-a
|| --->-o
! ---> !
iii) 判断字符串
(字符串这里有加上"$var" "quit")
-z 判断字符串是否为空
-n 判断字符串是否不为空
=或者== 判断是否相等 helloworld == helloboy
!= 判断是否不相等
\> 判断是否大于
\< 判断是否小于
IV) 对文件类型的判断
-e 判断文件是否存在
-s 判断文件是否存在,并判断文件是否为空
-b 判断文件是否存在,并判断文件是块设备
-c 判断文件是否存在,并判断文件是字符设备
-d 判断文件是否存在,并判断文件是否目录
-f 判断文件是否存在,并判断文件是普通文件
-L 判断文件是否存在,并判断文件是链接文件
-S 判断文件是否存在,并判断文件是套接字文件
-p 判断文件是否存在,并判断文件是管道文件
V) 对文件权限的判断
-r :判断是否具备读的权限
-w :判断是否具备写的权限
-x :判断是否具备可执行权限
1.9 输入语句-read
read 变量名 ----->类似于c的scanf
(1)将变量从终端上读取到shell脚本中
read 变量1 变量2 ...
(2)read可以同时读取多个变量的值
read -p "input var1 var2 > " var1 var2
(3)read可以跟一个-p参数在读取数据的时候
做打印提示信息
read -p "input arr" -a arr
echo ${arr[@]
(4)read可以通过-a参数读取一个数组
read -n 5 var1
(5)read加-n num指定读取num个字符
read -p "passwd : " -s var1
(6)read加-s输入的数据不会回显(静默模式)
read -t sec var1
(7)在sec秒钟内如果没有输入,read会向下执行。
如果有输入读取到输入的数据
read后跟的参数
-p:输入的时候提示
-a:输入的是数组
-n:指定输入的字符的个数
-s:输入的时候不显示
-t:指定超时时间
#!/bin/bash
#read var1 var2
#-p:后面可以加打印提示
#read -p "please input two values:" var1
var2
#-a:表示输入一个数组
#read -p "please input an array:" -a arr
#-n:指定输入的宽度:从终端最多获取5个字节给var1
#read -n 5 var1
#-s:输入不回显(静默模式)
#read -p "[sudo] edu118 的密码: " -s var1
read -t 5 var1
echo "var1 = $var1"
echo "var2 = $var2"
echo "var = ${arr[@]}"
1.10 输出语句-echo
-n:不换行
-e:解析转译字符(\n \t \r)
#!/bin/bash
#echo -n "helloworld"
#echo -n -e "nihao beijing" # -n:输出不换行
echo -n -e "helloworld\t"
echo "12345"
1.11 输出语句-printf
用法跟c一样,例如:
printf "%d-%02d-%02d %02d:%02d:%02d\r"
$year $month $day $hour $min $sec
#!/bin/bash
year=2023
month=10
day=7
hour=14
min=15
sec=0
for((;;))
do
printf "%4d-%-2d-%02d-%-2d:%-2d:%-2d\r"
$year $month $day $hour $min $sec
((sec++))
sleep 1
done
1.12 分支语句-case...in...
case 变量 in
匹配选项1)
语句1
;; # 相当于break
匹配选项2)
语句2
;;
*) #相当于default
语句n
;;
esac
匹配选项的格式:
* :匹配任意的字符
[字符1-字符n]:匹配[]内部的任意一个字符
"y"|"yes" :如果有多个可以使用|
,|.|:|\"|? :注意使用转译字符
#!/bin/bash
case $1 in
[A-Z]|"hello")
echo "这是大写字母 或者 hello"
;;
"yes"|"no"|'y'|'n')
echo "yes or no"
;;
,|\"|?)
echo "这是标点符号"
;;
*)
echo "其他标识符"
;;
esac
1.13 循环语句--while
(1) 语法格式
while ((判断条件))
do
done
(2) 注意事项
1.while循环条件只能使用(())来表示
2.while的循环体只能用do...done包含
(3) 示例
#!/bin/bash
sum=0
i=0
while ((i <= 100))
do
((sum+= i))
((i++))
done
echo "sum = $sum"
1.14 循环语句-for
[1]for的第一种用法(类似c语言风格的for循环)
for ((i=0;i<=100;i++))
do
循环体
done
[2]for的第二种用法(shell特有的for循环格式)
for 变量 in 单词列表
do
循环体
done
注:单词列表的格式
格式1:Ubuntu windows iphone Android
格式2:`ls`
格式3:{start..end}
格式4: 如果in和后面的单词列表都缺省,此时
单词列表是命令行的参数。
#!/bin/bash
for var1 in ubuntu redhat centos windows
ios
do
echo "var1 = $var1"
done
#!/bin/bash
for var1 in `ls /usr/include/`
{
echo "var1 = $var1"
}
#!/bin/bash
#for var1 in {1..100}
for var1 in {A..z}
do
echo "var1 = $var1"
done
#!/bin/bash
#循环将位置变量赋值给var
for var
do
echo "var = $var"
done
1.15 循环语句-select
select in增强交互效果的循环语句
select 变量 in 单词列表
do
循环体
done
bash
select var in ubuntu redhat ios centos
deepin win11
do
case $var in
"ubuntu")
echo "this is ubuntu"
;;
"redhat")
echo "this is redhat"
;;
"ios")
echo "this is ios"
;;
"centos")
echo "this is centos"
;;
"win11")
echo "this is win11"
;;
"deepin")
echo "this is deepin"
;;
*)
echo "输入有误"
;;
esac
done
1.16 break和continue
【2】break和continue
它和c语言的用法是一样的,只不过可以进行如下的使用
break n 退出n层循环
continue n 跳过n层循环,进而执行下一次循环