【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脚本文件

  1. shell脚本文件的名字一般以.sh结尾(不一定是.sh结尾的)
  2. 在shell脚本文件中本质上就是很多liunx命令的集合,
    并不是简单的将命令在shell脚本文件中罗列,会有一定的代码的逻辑。
  3. 当执行脚本文件时,脚本文件中的命令会按照逻辑依次执行,并完成一个特定的功能。

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与 name111name111是两种结果

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程远泊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值