目录
编译型语言:C、C++ ------>需要编译器
解释型语言:shell、python ------>需要解析器
shell---->贝壳
shell解析器:起到保护内核的作用,用户无法直接和内核层交换,通过指令和shell解析器完成用户和内核的交互
- 应用层:代码
- --------------------------- shell解析器
- 内核层:
- 内核层的五大功能:
- 1、内存管理
- 2、网络管理
- 3、进程管理
- 4、文件管理
- 5、设备管理
- ---------------------------
- 硬件层:外部设备
hello.sh ---->后缀是.sh
- #!/bin/bash
- # #!---->shebang
- # 指明脚本运行使用的shell解析器
-
-
- #这是一行注释
- echo "第一个shell脚本"
bash:现在市面上大部分linux都使用bash解析器
dash:比bash功能更少一点
sh:和终端的交互性不好
csh:类似C语言的模式
如何查看本机使用的shell解析器:echo $SHELL
- bash 文件名.sh ------>使用shell解析器去解析脚本
- bash在运行脚本时,会在后台打开一个新的终端,把运行的结果返回到当前终端
source是一个终端指令
source 文件名.sh source在同一个终端上运行和输出结果
chmod 777 脚本名
./脚本名
env ---->回显所有系统提供的环境变量
echo $PATH
PATH的作用,在终端执行指令或程序时,默认在PATH包含的路径中查找,如果程序/指令的路径不在PATH中,就会执行失败(未找到该命令)
修改PATH之后,可以直接输入可执行程序名执行程序,不需要再加上路径
一定不能修改原有的PATH路径
- export PATH=${PATH}:新的路径
- export PATH=${PATH}:/home/ubuntu/23061/day2
- export PATH = ${PATH} : /home/ubuntu/23061/day2
- | | | | | |
- 给(系统)变量赋值 要赋值的变量 赋值 拿到原有的PATH的值 路径分隔符 追加的新路径
vim ~/.bashrc --->打开用户的配置文件,把想要添加的路径使用export表达式添加到最后一行
让配置文件生效:
- 重启(永久生效)
- source ~/.bashrc (临时生效) ------>使用source和.是同一个指令
- . ~/.bashrc (临时生效)
修改/etc/environment
sudo vim /etc/environment
直接把想添加的路径,添加原有的路径后面
让配置文件生效:
- 重启(永久生效)
- source /etc/environment (临时生效) ------>使用source和.是同一个指令
- . /etc/environment (临时生效)
修改/etc/bash.bashrc
- sudo vim /etc/bash.bashrc
- 使用export表达式,将路径添加到最后
让配置文件生效:
- 重启(永久生效)
- source /etc/bash.bashrc (临时生效) ------>使用source和.是同一个指令
- . /etc/bash.bashrc (临时生效)
shell本身是擅长运行指令,shell是一个弱数据类型的语言
- C中:
- 存储类型 数据类型 变量名;
-
- shell中:
- 变量=变量的值 ----->如果变量的值中间没有空格直接使用
- 变量='变量的值' ----->变量的值中间有空格
- 变量="变量的值" ----->使用一个已有的变量给新的变量赋值,并且赋值中有空格时
- ''内,$变量名,不会被展开
注意:
- shell中等号两侧不允许有空格
- 如果有空格会把变量名识别成一个指令
- 在shell中如果使用变量的值,需要给变量名前加$
- $变量名 ${变量名}
- 1、使用已有的变量给新的变量赋值
- var1=hello
- var2=world
- var3="$var1 $var2"
shell脚本的本质:命令的集合
- C中
- int arr[4]={1,2,3,4};
-
- shell:
- 数组名=(1 2 3 4) ----->每个元素之间以空格作为分隔
-
- shell中支持稀疏数组
- 数组名=([下标]=初始值1 [下标]=初始值2 ·····)
-
- #!/bin/bash
- arr=(12 90 89 100)
-
- #shell中支持稀疏数组,下标不连续的数组
- brr=([0]=90 [3]=70 [7]=900)
-
- crr[0]=29 #给crr数组中下标为0的元素赋值
- crr[3]=78 #给crr数组中下标为3的元素赋值
-
- #再重新给brr中没有提供的下标的元素赋值
- brr[4]=67
-
- echo ${brr[4]}
- echo ${crr[3]}
- ${数组名[下标]}
-
- 访问数组中的所有元素
- ${数组名[*]}
- ${数组名[@]}
-
- ${#数组名[*]}
- #!/bin/bash
- arr=(12 90 89 100)
-
- #shell中支持稀疏数组,下标不连续的数组
- brr=([0]=,2 [3]=70 [7]=900)
-
- crr[0]=29 #给crr数组中下标为0的元素赋值
- crr[3]=78 #给crr数组中下标为3的元素赋值
-
- #再重新给brr中没有提供的下标的元素赋值
- brr[4]=67
-
- echo ${brr[@]}
- echo ${crr[*]}
- echo ${#brr[*]} #4 对于稀疏数组,#会记录数组中实际元素的个数
-
- echo ${#brr[0]} #2 对数组中的指定元素使用#,#记录元素中字符的个数
1、定义一个数组,使用外部参数给数组赋值,通过数组求外部参数的个数
2、把家目录的下的所有文件名放到数组中,并记录家目录下文件的个数
- #!/bin/bash
- arr=($*) #把所有的外部参数赋值给数组arr
- echo ${#arr[*]}
-
-
- arr2=(`ls ~`) #把家目录的所有文件名赋值给数组arr1
- echo ${#arr2[*]}
- echo ${arr2[@]}
- #!/bin/bash
- arr1=(1 2 3 4)
- arr2=(b n m l)
-
- #定义一个数组arr3,使用原来的arr1和arr2给新数组arr3赋值
- arr3=(${arr1[*]} ${arr2[*]})
- echo ${arr3[@]} # 1 2 3 4 b n m l
- arr3=(${arr1[*]}${arr2[*]})
- echo ${arr3[@]} #1 2 3 4b n m l
- echo ${#arr3[*]}
echo默认不解析转义字符并且会自动换行
-e:让echo指令解析转义字符
-n:取消换行
- #!/bin/bash
- echo "111\n" #echo默认不解析转义字符,会默认换行
- echo -e "111\n" #111 换行两次
- echo "111\n" -e #111\n -e echo的参数不能放在最后一个位置,被识别成字符串
- echo -ne "111\n" #让echo取消换行,-n参数
- read 变量名
- read -s 变量名 ---->输入的内容不回显
- read -p "提示信息" 变量名 ----->-p回显提示信息
- read -n 字符个数 变量名 ----->控制输入的字符个数,当超过会自动停止
- read -t 秒数 变量名 ----->控制读入数据的时间,如果指定时间内不输入会自动停止
- read -a 数组名 ---->输入数组
1、尝试把read除了-a以外的参数结合起来使用
- #!/bin/bash
- #read -p "请输入一个变量" var
- #read -n 3 var
- #read -t 3 var
- #read -a arr
- read -sp "请输入一个变量" -n 3 -t 4 var
- #echo ${#arr[*]}
- echo $var
shell本身不擅长算术运算,需要借助于运算符和其他指令
(()) $[] let expr
常用于shell中整数的算术运算
(())几乎支持所有的C语言语法,支持shell中的幂运算 **
使用方法:
- ((表达式1,表达式2,表达式3,····))每一个表达式都会执行,取到最后一个表达式的结果
- (())内使用变量时,可以加$也可以不加$
- (())内的运算符两侧,可以有空格也可以没有空格
- 变量名=$((表达式)),获取(())的运算结果
- 可以直接在(())内进行赋值操作,((var1 = var1+var2))
1、终端输入两个三位数,将其中一个自增,把两个变量赋值给第二个变量相加并输出
- #!/bin/bash
- read -p "请输入两个变量" var1 var2 #如果同一行获取两个变量,变量中间放空格
- ((var1++)) #自增
- ((var2=var1+var2))
- echo $var1
- echo $var2
- ((var1=var1**3)) #对var1进行幂运算
- echo $var1
2、求root用户的uid和ubuntu/linux用户gid相加的结果,比较这两个数的大小关系
- #!/bin/bash
- num1=`id -u root`
- num2=`id -g`
- echo $((num1+num2))
- #比较num1和num2的大小关系
- echo $((num1
- #比较num1和num2的大小关系
- echo $((num1
【2】$[]实现算数运算
使用方法: (仍然支持幂运算和自增自减运算)
- 变量名=$[表达式1,表达式2,表达式3,····],每一个表达式都执行,获取最后一个表达式的结果
- 运算时,运算符两侧可以有空格也可以没有空格
- 使用变量时,可以加$也可以不加$
- $[]本质上会遗留一个计算结果在,运算所在行,可以选择直接echo $[表达式] ,变量名=$[表达式]
- #!/bin/bash
- num1=100
- num2=30
- echo $[num1+num2] #直接在终端回显130
- echo $[num1++,num2**2,++num2] #31
- echo $num1 #101
- echo $num2 #31
练习:
1、计算当前目录下文件个数和家目录下文件个数的总和
2、计算家目录下.c和.sh文件的和
- #!/bin/bash
- arr=(`ls`)
- arr1=(`ls ~`)
- brr=(`ls` `ls ~`) #把两个路径下的文件,放到同一个数组中
- crr=(${arr[*]} ${arr1[*]}) #先把两个路径下的文件分别存在不同数组中,再拼接两个数组
- num1=${#arr[*]}
- num2=${#arr1[*]}
- echo $[num1+num2]
- echo ${#brr[*]}
- echo ${#crr[*]}
-
-
- arr3=(`ls ~/*.c`)
- arr4=(`ls ~/*.sh`)
- #对前两行的数组计数
- num3=${#arr3[*]}
- num4=${#arr4[*]}
- echo $[num3+num4]
【3】let实现算数运算
使用方法:
- let 变量名=表达式 ----->let和变量名中间一定有空格
- let使用变量可以加$,也可以不加$
- let运算时,运算符两侧一定不能有空格
- let 表达式,运算是可以进行的但是没有办法接收运算的结果
- #!/bin/bash
- num1=100
- num2=30
- let ret=num2**2 #支持幂运算
- let num1++ #支持自增运算,但是不能接收表达式的结果
- echo $ret
- echo $num1 #101
【4】expr
expr是一条指令
使用方法:
- expr使用变量的值时,必须加$
- 运算符两侧必须加空格 (不支持幂运算和自增自减运算)
- expr在使用时,一些字符需要转义,*,>,
- expr直接回显指令的执行结果到终端
- ARG1 | ARG2
- 如果ARG1的值不为0,结果就是ARG1,否则就是ARG2
-
- ARG1 & ARG2
- 如果RAG1和ARG2都不为0,结果是ARG1,否则是0
-
- ARG1 < ARG2
- ARG1 is less than ARG2
-
- ARG1 <= ARG2
- ARG1 is less than or equal to ARG2
-
- ARG1 = ARG2
- ARG1 is equal to ARG2
-
- ARG1 != ARG2
- ARG1 is unequal to ARG2
-
- ARG1 >= ARG2
- ARG1 is greater than or equal to ARG2
-
- ARG1 > ARG2
- ARG1 is greater than ARG2
-
- #!/bin/bash
- num1=-2
- num2=9
- : 'expr $num1 + $num2
- expr $num1 - $num2
- expr $num1 / $num2
- expr $num1 % $num2
- expr $num1 \* $num2
- '
- num3=0
- expr $num1 \| $num2
- expr $num1 \& $num2
- expr $num2 \> $num1
- expr $num2 != $num1
- expr $num2 = $num1
练习:
1、终端读入两个数据,使用expr比较大小关系
2、计算/etc/group中,第20行组用户gid和第10行组用户gid的和
- #!/bin/bash
- read -p "请输入两个变量" var1 var2
- expr $var1 \>= $var2
-
- #获取/etc/group中第20行用户的gid
- num1=`head -20 /etc/group | tail -1 | cut -d : -f 3`
- #获取/etc/group中第10行用户的gid
- num2=$(head -10 /etc/group | tail -1 | cut -d : -f 3)
- expr $num1 + $num2
expr对字符串的运算
- match str1 str2
- 返回str2在str1中完全匹配的个数(str2可以作为str1中子串)
-
- substr STRING POS LENGTH
- 如果字符串长度不够截取长度,就把字符串中所有的内容都截取出来
- 从string中的第pos个位置开始截取长度为length的子串(pos从1开始)
- index STRING CHARS
- 返回字符在字符串中第一次出现的位置,如果是多个字符,返回最先在字符串中出现的字符的下标
- (下标从1开始)
- length STRING
- 求字符串的长度
- #!/bin/bash
- str1=hello
- str2=hl
- expr match $str1 $str2 #0,因为hello中不能匹配到hl字符串
- expr substr $str1 2 3 #pos计数从1开始
- expr index $str1 lo #3l在hello最先出现
- expr length $str1
- expr length $str2
练习:
1、终端输入网址,如:www.baidu.com,要求:
接触网址每个部分,并放入数组中,不能使用cut,使用expr解决
- #!/bin/bash
- read -p "请输入一个网址" net
- len=`expr length $net` #网址的长度
- #找第一个.的位置
- pos1=`expr index $net .`
- #截取第一个.前面的所有子串
- arr[0]=`expr substr $net 1 $((pos1-1))`
-
- #为了找第二个.需要把后面的所有子串都截取出来
- str2=`expr substr $net $((pos1+1)) $len`
-
- #找到第二个.的位置
- pos2=`expr index $str2 .`
- arr[1]=`expr substr $str2 1 $((pos2-1))`
-
- arr[2]=`expr substr $str2 $((pos2+1)) $len`
- echo ${arr[*]}
八、shell中的分支语句
【1】if···else分支
- []就是test指令
- #单分支结构
- if [ test语句 ] -----> if test 表达式
- then
- 语句块
- fi
-
- #双分支
- if [ test语句 ] -----> if test 表达式
- then
- 语句块
- else
- 条件不成立执行的语句块
- fi
-
- #多分支语句
- if [ test语句 ] -----> if test 表达式
- then
- 语句块
- elif [ test语句 ] ------> elif test 表达式
- then
- 条件不成立执行的语句块
- fi
-
- #!/bin/bash
- num1=90
- num2=300
- #if [ $num1 -le $num2 ]
- if test $num1 -le $num2
- then
- echo "num1<=num2"
- fi
余下见链接
https://blog.csdn.net/ck0056/article/details/132816564
练习:
写一个1.sh脚本,将以下内容放到脚本中:
在家目录下创建目录文件,dir
在dir下创建dir1和dir2
把当前目录下的所有文件拷贝到dir1中,
把当前目录下的所有脚本文件拷贝到dir2中
把dir2打包并压缩为dir2.tar.xz
再把dir2.tar.xz移动到dir1中
解压dir1中的压缩包
使用tree工具,查看dir下的文件
- #!/bin/bash
- mkdir ~/dir
- mkdir ~/dir/dir2 ~/dir/dir1
- cp * ~/dir/dir1/ -r
- cp *.sh ~/dir/dir2/
- tar -cJf ~/dir/dir2.tar.xz ~/dir/dir2/
- mv ~/dir/dir2.tar.xz ~/dir/dir1/
- tar -xvf ~/dir/dir1/dir2.tar.xz
- tree ~/dir
-
相关阅读:
《TCP/IP网络编程》阅读笔记--基于UDP的服务器端/客户端
Spring 中不得不了解的姿势
模板引擎Thymeleaf和监听器
华为机试 - 水仙花数Ⅱ
Java随笔-HTTP
事务的隔离级别
副本机制在kafka中的实践
49. Group Anagrams
力扣(LeetCode)272. 最接近的二叉搜索树值 II(2022.09.29)
股票交易接口dll代码分享
-
原文地址:https://blog.csdn.net/ck0056/article/details/132745232