【shell基础篇】之入门系统学习大全
1.shell相关的概念
1.1编程语言分类
编译型语言:C/C++
执行使用gcc/g++
编译起来比较安全,编译只需要提供程序,不需要提供源码
解析型语言:shell/python
解释性语言需要使用解析器,对程序进行解析:bash解析器/sh解析器 python3解析器
解释型语言必须提供给用户源码,相对来说不安全
1.2shell使用的解析器
bash------>ubuntu终端使用的是bash解析器
sh ------>在开发板中使用sh解析器
ksh
sch
1.3什么是shell
shell翻译成中文:贝壳
shell是用来对linux系统起到保护的作用,通过输入命令,shell解析器解析输入的命令,
根据命令的功能最终实现硬件的控制,并将结果回显到终端之上。
1.4shell脚本文件
- shell脚本文件的名字一般以.sh结尾(不一定是.sh结尾的)
- 在shell脚本文件中本质上就是很多liunx命令的集合,
并不是简单的将命令在shell脚本文件中罗列,会有一定的代码的逻辑。- 当执行脚本文件时,脚本文件中的命令会按照逻辑依次执行,并完成一个特定的功能。
1.5第一个shell脚本文件
1. 创建一个01first.sh文件
2. 打开文件,添加以下内容
#!/bin/bash
# 使用的是那个脚本文件的解析器
echo "hello world"
3. 给脚本文件添加可执行的权限
chmod 0777 01first.sh
4. 执行脚本文件
4.1 方式1:
给脚本文件添加可执行权限之后,
./01first.sh 执行脚本文件
脚本文件必须具有可执行的权限,
会重新打开一个新的终端执行脚本文件,并将结果返回到当前终端之上。
4.2 方式2:
bash ./01first.sh
脚本文件可以不具有可执行的权限,
会重新打开一个新的终端执行脚本文件,并将结果返回到当前终端之上。
4.3 方式3:
source 01first.sh
脚本文件可以不具有可执行的权限,
在当前终端下执行脚本文件,并将结果返回到终端之上。
1.6练习题
#!/bin/bash
# your code
1.在⾃⼰的⽤户主⽬录下新建两个⼦⽬录subdir1 subdir2
cd ~
mkdir subdir1 subdir2
2.将/etc/passwd⽂件拷⻉到subdir1 ,将/etc/group 拷⻉到subdir2
sudo cp /etc/passwd subdir1
sudo cp /etc/group subdir2
3.将subdir2重命名为subdir
mv subdir2 subdir
4.对subdir1进⾏打包并且压缩成xz格式
tar -Jvcf subdir1.tar.xz subdir1
5.将打包后的xz格式⽂件拷⻉到subdir⽬录下
cp subdir1.tar.xz subdir
6.解压subdir⽬录下的压缩格式⽂件
tar -vxf subdir/subdir1.tar.xz
7.查看subdir⽬录下所有的⽂件
ls subdir -al
1.7vscode常用快捷键
ctrl+b,隐藏工程
ctrl+~,调出终端
2.shell变量的使用
2.1shell中变量的介绍
在shell中的变量没有数据类型之分,所有的变量都当成字符串看待。
name=zhoukai —> 字符串
age=10000 —> 10000被当成字符串处理
2.2shell中定义变量的格式
变量名=初始值
注:
1.变量名的书写跟C语言一致
2.在shell中定义变量时,等号两边不要出现空格
3.在shell中定义变量时有3种格式:
变量名=初始值
变量名=’初始值‘
变量名=“初始值”
只要没有空格,哪种方式都可以
4.定义shell变量时,如果变量的值有空格,此时需要使用单引号,双引号括起来
5.定义shell中的变量时,如果使用shell中的一个变量对另一个变量赋值时,需要使用一个“ ”括起来
var1=hello
var2=${var1} #ok
var3=‘${var2} world’ #语法没有错误 单引号中的变量不展开,当成普通字符串处理
结果:var3=${var2} world
var4=“${var2} world” #ok 结果:var4=hello world
2.3shell中变量的使用
${变量名}
或者
$变量名
推荐使用{ } ,原因: n a m e 111 与 {name}111与 name111与name111是两种结果
2.4shell中的位置变量
在执行shell脚本文件时,给shell脚本文件传递参数,在shell脚本文件中获取执行脚本文件传递的参数,需要使用位置变量。
$0 --------> 用来获取执行的脚本文件的名字
$1 --------> 用来获取执行的脚本文件的第一个参数
$2 --------> 用来获取执行的脚本文件的第二个参数
$3 --------> 用来获取执行的脚本文件的第三个参数
…
n − − − − − − − − > 用来获取执行的脚本文件的第 n 个参数 ( n > = 10 时,使用花括号,例: n --------> 用来获取执行的脚本文件的第n个参数(n>=10时,使用花括号,例: n−−−−−−−−>用来获取执行的脚本文件的第n个参数(n>=10时,使用花括号,例:{10}不然会当做1 和 0)
$# ----> 执行shell脚本文件时传递的参数个数之和,不包括脚本文件名自身。
$@ ----> 获取执行脚本文件时传递的所有的参数,不包括脚本文件名自身。
$* ----> 获取执行脚本文件时传递的所有的参数,不包括脚本文件名自身。
$? ----->返回程序执行后的状态,返回0表示执行成功
$$ ----->程序本身的PID号
#!/bin/bash
# your code
echo '$0'=$0 # 获取脚本文件的名字
echo '$1'=$1 # 获取第一个参数
echo '$2'=$2
echo '$3'=$3
echo '$4'=$4
echo '$5'=$5
echo '$6'=$6
echo '$7'=$7
echo '$8'=$8
echo '$9'=$9 # 获取第九个参数
echo '$10'=$10 # 获取第一个参数和0字符拼接
echo '${10}'=${10} # 获取第10个参数
echo '$#'=$# # 获取参数的个数之和,不包括执行脚本文件的名字
echo '$@'=$@ # 获取所有的参数,不包括执行脚本文件的名字
echo '$*'=$* # 获取所有的参数,不包括执行脚本文件的名字
2.5修饰变量的关键字
1.readonly ------>修饰只读变量
作用:修饰只读变量,修饰变量时必须初始化
2.unset ---------->取消变量的定义
3.local ----------->定义局部变量
作用:在shell中定义的变量都是全局变量,只有在local关键字下定义是局部变量(在函数中可用)
#!/bin/bash
# your code
readonly a=yaoliang
# a=lll 提示错误
b=19;
echo "定义变量时打印:$b"
unset b
echo "取消定义后:$b"
function func()
{
local c=100;
}
echo "c=$c" #c=100
func
echo "c=$c" #c=
2.6命令置换符
$(shell命令)或者 'shell命令 ’
``:是反向单引号,是电脑键盘破折号上的哪个单引号
作用: 使用命令置换符可以将命令的执行的结果赋值给一个变量。
变量名=$(shell命令)
变量名=` shell命令 ``
file=$(ls .)
echo "file=$file"
filepath=`pwd`
echo "filepath=$filepath"
3.shell中数组的定义
在shell中只支持一维数组的定义,不支持多维数组的定义
3.1shell中数组定义的格式
数组名=(成员0 成员1 成员2…)
----------->数组中的成员是连续的
数组名=([0]=成员0 [2]=成员2…)
------------>数组中成员不是连续的
3.2在shell中数组成员的访问
1.修改数组中某个成员的值
数组名[index(下标)]=新的初始值
2.读取数组成员的值
${数组名[index]}
3.读取数组中所有成员的值
${数组名[*]}
${数组名[@]}
4.统计数组中成员的个数
${#数组名[*]}
${#数组名[@]}
5.统计数组中成员单个元素的个数
${#数组名[index]}
3.3在shell中实现数组的拼接
数组名=( 数字名 1 [ ∗ ] {数字名1[*]} 数字名1[∗]数字名2[ *])
数组名=( 数字名 1 [ @ ] {数字名1[@]} 数字名1[@]数字名2[ @])
3.4练习
#!/bin/bash
# your code
# 数组名=(成员0 成员1 成员2..........)
arr1=(11 22 33 44)
# ----------->数组中的成员是连续的
# 数组名=([0]=成员0 [2]=成员2..........)
arr2=([0]=AA [2]=BB [3]=CC)
# ------------>数组中成员不是连续的
# 1.修改数组中某个成员的值
arr1[0]=55
arr2[0]=DD
# 数组名[index(下标)]=新的初始值
# 2.读取数组成员的值
echo arr1[0]=${arr1[0]}
echo arr2[0]=${arr2[0]}
# ${数组名[index]}
# 3.读取数组中所有成员的值
echo arr1[*]=${arr1[*]}
echo arr2[*]=${arr2[*]}
# ${数组名[*]}
echo arr1[@]=${arr1[@]}
echo arr2[@]=${arr2[@]}
# ${数组名[@]}
# 4.统计数组中成员的个数
echo '#'arr1[*]=${#arr1[*]}
echo '#'arr2[*]=${#arr2[*]}
# ${#数组名[*]}
echo '#'arr1[@]=${#arr1[@]}
echo '#'arr2[@]=${#arr2[@]}
# ${#数组名[@]}
# 5.统计数组中成员单个元素的个数
echo '#'arr1[0]=${#arr1[0]}
echo '#'arr2[0]=${#arr2[0]}
# ${#数组名[index]}
arr3=(aa bb cc)
arr4=(ee ff gg)
# 数组名(${数字名1[*]}$数字名2[ *])
arr5=(${arr3[*]} ${arr4[*]})
echo arr5[*]=${arr5[*]}
# 数组名(${数字名1[@]}$数字名2[ @])
arr5=(${arr3[@]} ${arr4[@]})
echo arr5[@]=${arr5[@]}
4.shell中的算数运算
1.shell脚本语言不擅长算数运算,shell更擅长文件的判断和处理
2.由于shell没有数据类型之分,都当成字符串处理
因此shell运算中要借助算数符号或者借助算数运算相关的算数运算相关命令
3.在shell中使用算数运算
3.1(())完成
3.2$[]完成
3.3expr命令
4.1(())完成算数运算
格式:
((算数表达式1,算数表达式2,算数表达式3…))
最后一个算数表达式结果作为返回值
获取运算结果:
ret_val=$((算数表达式))
或者
((ret_val=算数表达式))
注意事项:
1>如果在表达式中使用其他变量时,可以加$,也可以不加
2>运算符两边可以存在空格
#!/bin/bash
# your code
# ((算数表达式1,算数表达式2,算数表达式3......))
# 最后一个算数表达式结果作为返回值
ret_val=$((1+2,1>2))
echo "ret_val=$ret_val"
# 运算符两边可以存在空格
((ret_val1=1+2,ret_val2 = 2+3))
echo "ret_val1=$ret_val1"
echo "ret_val2=$ret_val2"
# 如果在表达式中使用其他变量时,可以加$,也可以不加
a=100
b=200
ret_val3=$((a+b))
ret_val4=$(($a-$b))
echo "ret_val3=$ret_val3"
echo "ret_val4=$ret_val4"
4.2$[]完成算数运算
格式:
$[算数表达式1,算数表达式2,算数表达式3…]
最后一个算数表达式结果作为返回值
获取运算结果:
ret_val=$[算数表达式]
注意事项:
1>需要有一个变量接收$[]运算后的结果
2>如果在表达式中使用其他变量时,可以加$,也可以不加
3>运算符两边可以存在空格
#!/bin/bash
# your code
# $[算数表达式1,算数表达式2,算数表达式3......]
# 最后一个算数表达式结果作为返回值
ret_val=$[1+2,1>2]
echo "ret_val=$ret_val"
# 运算符两边可以存在空格
ret_val1=$[1+2]
ret_val2=$[2+3]
echo "ret_val1=$ret_val1"
echo "ret_val2=$ret_val2"
# 如果在表达式中使用其他变量时,可以加$,也可以不加
a=100
b=200
ret_val3=$[a+b]
ret_val4=$[$a-$b]
# $[ret_val5=b%a] error
echo "ret_val3=$ret_val3"
echo "ret_val4=$ret_val4"
# echo "ret_val5=$ret_val5"
4.3expr命令算数运算符
1.ecpr是一个命令,可以去man查看
2.格式:
expr 表达式
3.获取命令的执行结果------->需要使用命令置换符
ret_val=`expr 表达式 ``
ret_val=$(expr 表达式)
4.注意事项:
1>在expr命令中使用变量必须要使用$
2>表达式中的运算符两边必须加空格
expr “ a " + " a" + " a"+"b” #运算结果正确
expr “ a " + " a"+" a"+"b” #运算结果错误,语法没有错误,整体当成一个字符串输出
原因:expr是一个命令,如果没有空格,没办法正确传参。
3>在使用expr时,部分运算符需要转义
\( \) \< \> \>= …
需要转义运算符不需要记忆,使用时,具体看结果
4>使用expr命令时,不可以自增自减操作
expr $a++ #error
expr $a-- #error
expr $a+1 #ok
expr $a-1 #ok
#!/bin/bash
# your code
# ret_val=`expr 表达式 `
# ret_val=$(expr 表达式)
a=10
b=20
# 1>在expr命令中使用变量必须要使用$
# 2>表达式中的运算符两边必须加空格
ret_val=`expr $a + $b `
ret_val1=$(expr $a + $ret_val)
echo "ret_val=$ret_val"
echo "ret_val1=$ret_val1"
# 3>在使用expr时,部分运算符需要转义
# \\( \\) \\< \\> \\>= .....
# 需要转义运算符不需要记忆,使用时,具体看结果
ret_val2=$(expr \( $ret_val + $ret_val1 \) \/ 2)
echo "ret_val2=$ret_val2"
# 4>使用expr命令时,不可以自增自减操作
# ret_val3=`expr $ret_val2++`#error
ret_val3=`expr $ret_val2 + 1` #ok
echo "ret_val3=$ret_val3"
# 与运算
ret_val4=`expr $ret_val2 \& $ret_val3`
echo "ret_val4=$ret_val4"
字符串处理
expr match STRING REGEXP
从STRING字符串中和REGEXP字符串进行比较,如果比较成功返回相同字符的个数,
不成功返回0,从第一个字符开始比较
expr substr STRING POS LENGTH
从STRING字符串中截取子字符串,POS从那个位置开始截取,LENGTH截取字符串的长度;
注:STRING字符串的第一个字符的起始编号为1
expr index STRING CHARS
从STRING字符串中查找第一次出现CHARS字符的位置,成功返回字符的编号,没有找到返回0;
如果一个字符串中有多个CHARS,返回第一次出现此字符的位置
注:STRING字符串的第一个字符的起始编号为1
expr length STRING
计算字符串的长度 等价于${#STRING}
#!/bin/bash
# your code
str="helloworld"
# 1.匹配hello字符的个数,子字符串永远都和母字符串的第一个比较
expr match "$str" "hello" #从第一个开始比较,结果为5
expr match "$str" "world" #从第一个开始比较,结果为0
expr match "$str" "hellw" #从第一个开始比较,结果为0
#2.截取子字符串
expr substr "$str" 6 5
#3.查找'o'字符的位置
expr index "$str" 'o'
#4.统计字符串的长度
expr length "$str"
练习(网站域名):
#!/bin/bash
# your code
end=`expr index $1 '.'`
arr[0]=`expr substr $1 1 $((end-1)) `
len=`expr length $1`
newstr=`expr substr $1 $(($end+1)) $(($len-$end))`
end=`expr index $newstr '.' `
arr[1]=`expr substr $newstr 1 $(($end-1))`
len=`expr length $newstr`
arr[2]=`expr substr $newstr $(($end+1)) $(($len-$end))`
echo ${arr[*]}
5.test命令(重要)
1.经常与if分支语句结合使用
if test 表达式 ;then
shell语句
else
shell语句
fi
if [表达式] ;then #[]相当于test命令,使用[]最终调用的是test命令
shell语句
else
shell语句
fi
2.test可以用来实现整数比较,字符串比较,逻辑运算,文件的判断
3.在使用test命令时,如果使用了其他的变量,必须通过使用$,变量使用" "括起来
4.在使用test([])的表达式中,表达式的变量,参数,运算符的前后必须添加空格
5.在test中使用部分运算符时需要进行转义 ,eg:\(
5.1整数比较
-eq : 等于
-ne : 不等于
-gt : ⼤于
-lt : ⼩于
-ge : ⼤于等于
-le : ⼩于等于
[ INTEGER1 -eq INTEGER2 ]
5.2逻辑运算
-a 与 &&
-o 或 ||
! ⾮ !
练习题:学生成绩
#!/bin/bash
# your code
read -p "请输入学生的成绩" score
#如果一个[]使用-o -a !
# if [ "$score" -lt 0 -o "$score" -gt 100 ];then
# echo "输入的成绩不合理,请重新输入"
# exit
# fi
#如果两个[]使用&& || !
if [ "$score" -lt 0 ] || [ "$score" -gt 100 ];then
echo "输入的成绩不合理,请重新输入"
exit
fi
if [ "$score" -ge 90 ] ; then
echo "A"
elif [ "$score" -ge 80 ] ; then
echo "B"
elif [ "$score" -ge 70 ] ; then
echo "C"
elif [ "$score" -ge 60 ] ; then
echo "D"
else
echo "E"
fi
5.3字符串的比较
字符串对象(⼀定要注意在进⾏字符串的判断的时候都需要加上“”,“$a” "hello")
-z 判断字符串是否为空 ----> 为空返回真,非空返回假
-n 判断字符串是否为⾮空 ---> 非空为真,空为假
=或== 都是⽤来判读字符串是否相等 ---> 成立返回真,不成立返回假
!= 不等于 ---> 成立返回真,不成立返回假
\> ⼤于 (防⽌误认为重定向) ---> 成立返回真,不成立返回假
\< ⼩于 ---> 成立返回真,不成立返回假
[ STRING1 = STRING2 ]
练习题:执行shell脚本时传递两个字符串,并对字符串进行判断
#!/bin/bash
# your code
#判断参数的个数之和是否为2个
if [ $# -eq 2 ];then
if [ $1 = $2 ] ; then
echo "$1 和 $2 字符串相等"
elif [ $1 \> $2 ] ; then
echo "$1 大于 $2 字符串"
elif [ $1 \< $2 ] ; then
echo "$1 小于 $2 字符串"
fi
else
echo "传参错误!"
echo "usage:./$0 STRING1 STRING2"
exit
fi
5.4文件的比较
1. 文件类型的判断
-b filename 判断⽂件是否存在,是否是块设备
-c filename 判断⽂件是否存在,是否是字符设备
-d filename 判断⽂件是否存在,是否是⽬录
-f filename 判断⽂件是否存在,是否是普通⽂件
-p filename 判断⽂件是否存在,是否是管道⽂件
-L filename 判断⽂件是否存在,是否是链接⽂件 (经测试链接⽂件也是普通⽂件)
-S filename 判断⽂件是否存在,是否是套接字⽂件
-e filename 判断⽂件是否存在
-s filename 判断⽂件是否存在,判断⽂件是否为空
[ -b filename ]
2. 文件权限的判断
-r filename 判断⽂件是否存在,是否有可读权限
-w filename 判断⽂件是否存在,是否有可写权限
-x filename 判断⽂件是否存在,是否有可执⾏权限
[ -r filename ]
3. 文件时间戳比较
-nt ⽂件是否更新
-ot ⽂件是否更旧
-ef ⽂件的inode是否⼀致
[ filename1 -nt filename2 ]
练习:1.请输⼊⽂件的名字,判断⽂件是否是普通⽂件,还是⽬录,若是普通文件,判断文件是否为脚本文件,如果为脚本文件,判断脚本文件是否具有可执行的权限,如果没有可执行的权限则添加可执行的权限。
#!/bin/bash
# your code
if [ $# -eq 0 ];then
echo "传参错误!"
echo "usage:./$0 STRING1"
exit
else
if [ -e $1 ];then
if [ -d $1 ];then
echo "$1是目录文件"
elif [ -f $1 ];then
echo "$1是普通文件"
filetype=`file $1 | cut -d " " -f 3 `
if [ "$filetype" == "shell" ];then
echo "$1是脚本文件"
if [ -x $1 ];then
echo "$1是可执行文件"
else
echo "$1不是可执行文件"
chmod a+x $1
ls $1 -l
fi
elif [ "$filetype" != "shell" ];then
echo "$1不是脚本文件"
fi
fi
else
echo "$1是其他文件"
fi
fi
6.常用语句
6.1if分支语句
6.1.1if分支语句格式
1.if分支,没有else分支
if((表达式))
then
shell语句
fi
2.if...else分支
if((表达式))
then
shell语句
else
shell语句
fi
3.if...elif分支
if((表达式))
then
shell语句
elif((表达式))
then
shell语句
else
shell语句
fi
如果if和then放在一行去写,需要中间加个;
eg: if((表达式));then
shell语句
fi
6.1.2if分支语句的练习题
输入工资,最终决定使用的交通工具
#!/bin/bash
# your code
read -p "请输入你的薪资>" salary
if((salary < 0))
then
echo "输入薪资错误!请重新输入"
exit
fi
if((salary<10000));then
echo "骑自行车上班"
elif((salary<20000));then
echo "骑电动车"
elif((salary<30000));then
echo "开汽车上班"
elif((salary<40000));then
echo "使用曹操专车出行"
else
echo "出行方式自由选择"
fi
6.2case…in分支语句
6.2.1case…in分支语句的语法格式
1.语法格式:
case 常量表达式 in ----->等价于switch ... case 语句
常量1) ----->等价于C语言中的case常量;
shell语句 ----->等价于c语句
;; ---->等价于break;
常量2)
shell语句
;;
常量3)
shell语句
;;
*) ------>等价于"default:"分支
shell语句
;;
esac
2.注意事项:
1>;;不可以省略,最后一个分支;;可以省略
2>case中的分支的写法
a)---->表示字符a
a|b|c)---->表示字符a,b,c中的任意一个
1|2|3)---->表示数字1,2,3中的任意一个
y|yes|YES)--->表示字符串中的任意一个
[a-zA-Z])---->表示a-z,A-Z中的任意一个字符
[1-9])----->表示1-9中的任意一个整数
*)------>使用*通配符
练习1:判断成绩
#!/bin/bash
# your code
read -p "请输入学生成绩>" score
if [ \( $score -lt 0 \) -o \( $score -gt 100 \) ];then
echo "输入的成绩错误,请重新输入"
exit
fi
case $((score/10)) in
10|9)
echo "A"
;;
8)
echo "B"
;;
7)
echo "C"
;;
6)
echo "D"
;;
*)
echo "E"
;;
esac
练习题2:从终端输入一个字符,判断字符时字母,还是数字,还是标点符号。
#!/bin/bash
# your code
read -p "请输入一个字符 >" ch
case $ch in
[a-zA-Z])
echo "$ch 是一个字母"
;;
[0-9])
echo "$ch 是一个数字"
;;
\,|\.|\!|\;|\?)
echo "$ch 是一个标点符号"
;;
*)
echo "$ch 啥也不是"
;;
esac
6.3while循环语句
6.3.1while循环语句的格式
1.格式1:
while ((表达式))
do
shell语句
done
2.格式2:
while [表达式]
do
shell语句
done
while语句1经常和test命令结合使用
3.格式3:
while [ true ] ------->等价于while(1);
do
shell语句
done
练习:1-100求和
#!/bin/bash
# your code
sum=0
i=1
while [ $i -le 100 ]
do
((sum=sum+i))
((i++))
done
echo "sum=$sum"
while (( i <= 100 ))
do
((sum=sum+i))
((i++))
done
echo "sum=$sum"
6.4for循环语句
6.4.1for循环语句的语法格式
1.类似于C语言的for循环语句
for((表达式1;表达式2;表达式3))
do
shell语句4
done
2.类似于python格式的for循环
for 变量名 in 字符串格式的单词列表,字符串单词之间使用空格隔开
do
shell语句
done
练习1:从终端输入字符串,给数组进行初始化,并使用for循环将数组中的值打印
#!/bin/bash
# your code
#定义一个空数组,数组长度为5
arr=()
echo "给数组赋值"
for ((i=0;i<5;i++))
do
read -p "arr[$i] = " arr[$i]
done
echo "遍历数组:"
for index in 0 1 2 3 4
do
echo "arr[$index] = ${arr[$index]}"
done
练习2:通过终端输入行数,打印以下图形
*
**
***
****
*****
.......
#!/bin/bash
# your code
read -p "请输入打印几行>" line
for ((i=1;i<=$line;i++))
do
for ((j=0;j<i;j++))
do
echo -n "*"
done
echo " "
done
#seq 命令,可以输出等差数列
#seq 起始数字 相邻连续数组的差值 结束数字
#eg:seq 0 2 10 结果:0 2 4 6 8 10
#eg:seq 0 10 结果:0 1 2 3 4 5 6 7 8 9 10 默认差值为1
for i in `seq 1 $line`
do
for j in `seq 1 $i`
do
echo -n "*"
done
echo " "
done
练习题3:定义一个数组,比如arr=(10 40 20 60 90 110 25 70 50 120),使用冒泡的方式对数组进行排序。
#!/bin/bash
# your code
#!/bin/bash
# your code
#定义一个空数组,数组长度为5
arr=()
read -p "请输入数组元素个数>" n
echo "给数组赋值:"
for ((i=0;i<$n;i++))
do
read -p "arr[$i] = " arr[$i]
done
# for ((i=0;i<$[$n-1];i++))//方法一
for i in `seq 0 \`expr ${#arr[*]} - 2\``//方法二
do
# for((j=0;j<$[$n-1-i];j++))
for j in `seq 0 \`expr ${#arr[*]} - 2 - $i\``
do
if [ ${arr[$j]} -le ${arr[$j+1]} ];then
temp=${arr[$j]}
arr[$j]=${arr[(($j+1))]}
arr[(($j+1))]=$temp
fi
done
done
echo "遍历数组:"
for index in `seq 0 1 $[$n-1]`
do
echo "arr[$index] = ${arr[$index]}"
done
6.5select…in选择分支语句
6.5.1select的语法格式
select 变量名 in 单词列表:单词之间使用空格隔开
do
shell语句
done
6.5.2参考案列
#!/bin/bash
# your code
select num in ONE TWO THREE
do
echo $num
done
执行结果:
1) ONE
2) TWO
3) THREE
#? 1
ONE
#? 2
TWO
#? 1
ONE
#?
结束 :ctrl + c
使用select…in的好处 提高代码交互功能,经常和case…in结合使用
练习:打开系统
#!/bin/bash
# your code
select os in windows linux ios Android
do
case $os in
windows)
echo "打开$os系统"
;;
linux)
echo "打开$os系统"
;;
ios)
echo "打开$os系统"
;;
Android)
echo "打开$os系统"
;;
esac
done
6.6break和continue
6.6.1break和continue的语法格式
1.break的语法格式
break n ------->n大于等于1,退出n层循环体(n=1,可以省略不写)
2.continue
continue n-------->n大于等于1,退出n层本次循环(n=1,可以省略不写)
6.6.2测试
break
#!/bin/bash
# your code
for i in `seq 0 5`
do
echo -n "*"
for j in `seq 0 5`
do
echo -n "#"
if [ $j -gt 3 ] ; then
break 2
fi
done
done
echo ""
# 结果:*#####
continue
#!/bin/bash
# your code
for i in `seq 0 2`
do
echo -n "*"
for j in `seq 0 5`
do
echo -n "#"
if [ $j -gt 3 ] ; then
continue 2
fi
done
done
echo ""
# 结果:*#####*#####*#####
7.shell中的函数
7.1shell中函数的定义
格式:
function 函数名()
{
函数体
}
注:
1>在shell中定义函数时,需要加function修饰,function可以省略,但不推荐
2>遵循先定义后使用的原则
3>shell函数中没有规定的返回值类型,可以自己定义
4>shell函数不需要写形参列表,及()中不需要写任何的东西,由自己决定
7.2shell中函数的调用
shell函数没有形参时的调用方式:
shell函数名
shell函数有实参值时传递调用:
shell函数名 实参列表(多个实参之间使用空格隔开)
7.3在shell函数中获取函数调用传递实参值
使用位置变量获取函数调用的实参值
$1
$2
…
${n} ---->获取函数传递实参值的第n个
$* ------>获取所有的实参值
$@ ------>获取所有的实参值
$# ------>获取所有的实参值的个数
7.4shell中函数的返回值
方式1:
在shell中定义全局变量,在函数外可以使用全局变量
方式2:
通过return关键字返回 在shell函数中使用local关键字修饰的局部变量,通过return返回局部变量的值,return只能返回0-255之间的值
$?可以获取返回的结果
方式3:
在shell函数中使用echo命令输出一个局部变量的值,在调用函数时,
给函数添加命令置换符(``ret_cal=
函数名 参数
)
7.5参考案列
#!/bin/bash
# your code
#1.定义一个函数,没有参数没有返回值
function print()
{
echo "hello"
}
#2.定义一个函数,函数具有参数值,没有返回值
function arr_sum()
{
sum=0;
for val in $*
do
((sum=$sum+$val))
done
echo "sum=$sum"
}
# 3.定义函数有实参有返回值,通过全局变量返回
function add_func()
{
((add_sum=$1+$2))
}
# 4.定义函数,函数有实参,有返回值,通过return返回
function add_func1()
{
local add_sum1=0
((add_sum1=$1+$2))
return $add_sum1
}
# 5.通过echo命令输出局部变量的值
function add_func2()
{
local add_sum2=0
((add_sum2=$1+$2))
echo "$add_sum2"
}
#1.函数的调用
print
# 2.函数调用
arr=(10 20 30 40 50)
arr_sum ${arr[*]}
# 3.函数调用
add_func 1000 2000
echo "$add_sum"
# 4.函数调用,return只能返回0-255之间的数
add_func1 10 20
echo "10+20=$?"
# 5.函数调用
add_func2 100 200 #在函数中直接打印出结果
# 通过转义把命令赋值给变量
ret=`add_func2 100 200 `
echo ret=$ret
练习题:通过终端输入用户名,判断用户是否存在,获取用户名对应的uid
1> 输⼊⽤户的名字,判断该系统上是否存在该⽤户
(封装为函数get_user_line(),若⽤户存在则返回用户名/etc/passwd中的⾏号)
提示:line=grep "^输入的用户名" /etc/passwd -n | cut -d ":" -f 1
2> 若存在该⽤户将这个⽤户名uid显示出来
(封装为函数get_user_info(),将上述的函数返回的⾏号传递到这个函数中,返回uid)
提示:uid=head -$line /etc/passwd | tail -1 | cut -d ":" -f 3
#!/bin/bash
# your code
if [ $# -eq 0 ];then
echo "传参错误"
echo "usage:./$0 STRING1"
fi
function get_user_line()
{
local line=`grep "^$1" /etc/passwd -n | cut -d ":" -f 1`
return $line
}
function get_user_info()
{
uid=`head -$line /etc/passwd | tail -1 | cut -d ":" -f 3`
echo $uid
}
get_user_line $1
line=$?
if [ $line -gt 0 ];then
echo "用户存在"
info=`get_user_info $line`
echo "$1 uid = $info"
else
echo "用户不存在"
fi