首页 > 系统相关 >shell脚本之 shell编程

shell脚本之 shell编程

时间:2024-01-29 12:22:59浏览次数:22  
标签:脚本 文件 aa shell 变量 编程 echo 判断 环境变量

1. Bash的变量

shell中变量的设置规则

  • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头
  • 在Bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型
  • 变量使用等号连接,等号左右两侧不能有空格
  • 如果变量的值有空格(Linux中空格代表分割),需要使用单引号或双引号包括
  • 在变量的值中,可以使用\转义符
  • 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含$变量名或者使用${变量名}
  • 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或者$()包含变量
  • 建议环境变量使用大写

变量分类

用户自定义变量

环境变量:这种变量中主要保存的是和系统操作环境相关的数据

位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的

预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的

1.1 用户自定义变量(本地变量)

  • 变量定义 aa=123 注意等号左右不能有空格

  • 变量叠加 两种方式aa="$aa"456或者aa=${aa}789

  • 变量查看 set

  • 变量删除 unset name

可以看到这四种变量从上到下变量是越来越严格的

1.2 环境变量

环境变量和用户自定义变量的区别

用户自定义变量 只在当前的Shell中生效,

而环境变量会在当前Shell和这个Shell的所有子Shell当中生效,如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的Shell中生效

环境变量和用户自定义变量的区别在于 作用的范围不同

如何设置环境变量

export 变量名=变量值 声明环境变量

env 查询变量

unset 变量名 删除变量

$变量名 调用变量

什么是父shell ,和子shell

直接进入Linux是bash环境,如果再次输入bash即进入shell的子shell中,可以使用pstree命令来查看shell的结构,最后使用exit命令即可退出子shell

可以使用set或者env命令来查看系统中的变量

系统常见的环境变量

PATH 是系统查找命令的路径

在ubuntu中输入$PATH命令,输出为

-bash: /home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory

从这里我们也可以看出来上次得到的 在bin目录中存放的是常用的可执行文件

在Linux系统中一切都是文件,我们输入的命令都是文件,那么为什么执行shell脚本的时候需要添加路径,而执行正常命令的时候却不要呢?

因为正常命令的路径已经存放在PATH当中去了,而Linux在执行命令时会首先在PATH中搜索,所以执行正常命令时不用添加路径

当然,我们也可以把我们的脚本存放在PATH中,这样就可以不用输入路径就可以执行,不过我们通常不会直接把这样的脚本直接添加到PATH中,因为这样可能会对原系统改动

如果想要直接运行脚本,而不用每次添加路径,更为保险的做法是利用变量叠加添加脚本所在路径,

PATH="$PATH":/root 通过这条命令,我们就把root目录存放在PATH中了,可以再次使用$PATH命令查看是否已经添加了/root目录,不过这只是临时生效,想要永远生效需要写入配置文件

PS1 定义系统提示符的命令

1.3 位置参数变量

其实就相当于编程中的函数传递参数

位置参数变量 作用
$n n为数字,$0代表命令本身,$1-$9表示接受第一个到第九个的参数,十以上的参数需要用大括号包含,如${10}
$* 这个变量代表命令行所有的参数,$*把所有的参数看成一个整体
$@ 这个变量也代表命令行中的所有参数,不过$@把每个参数区分对待
$# 这个变量代表命令行中所有参数的个数

下面是一个例子

#!/bin/bash
# 位置参数的功能

echo "A total of $# parameters"
#使用$#代表所有参数的个数
echo "The parameters is : $*"
#使用$*代表所有的参数
echo "The parameters is : $@"
#使用$@也代表所有的参数

./Loca.sh 12 34 56

输出为

A total of 3 parameters
The parameters is : 12 34 56
The parameters is : 12 34 56

1.4 预定义变量

预定义变量 作用
$? 最后一次执行的命令(上一条命令)的返回状态。如果这个命令的值为0,证明上一个命令正确执行,如果这个变量的值为非0(具体是哪个数,由命令自己决定),则证明上一个命令执行不正确
$$ 当前进程的进程号(PID)
$! 后台运行的最后一个进程的进程号(PID)
  • $?可以判断上一条命令是否正确

1.5 使用read接受键盘输入

read [选项] [变量名]

选项:

-p 提示信息 在等待read输入时,输出提示信息

-t 秒数 read可以一直等待用户输入,使用此选项可以指定等待时间

-n 字符数 read命令只接受指定的字符数,就会执行

-s: 隐藏输入的数据,

通过下面这个例子来体会

#!/bin/bash

read -t 30 -p "Please input your name: " name  #在shell脚本中,一定注意空格的使用,此处要添加空格
# -p  提示“请输入姓名”并等待30秒,把用户的输入保存入变量name中
echo "Name is $name"
echo -e "\n"

read -s -t 30 -p "Please input your age(using hidden mode): " age
# 年龄是隐私,所以我们用-s选项隐藏输入
echo "\t"
echo "Age is $age"
echo -e "\n"

read -n 1 -t 30 -p "Please select your gender[M/F]: " gender
#使用"-n 1"选项只接收一个输入字符就会执行(不用输入回车会直接执行)
echo -e "\n"
echo "Sex is $gender"

2. Bash运算符

2.1 数值运算与运算符

方法一 declare声明变量类型

语法:declare [+-][选项] 变量名

选项:

- 给变量设定类型属性

+ 取消变量的类型属性

-i 将变量声明为整数型(integer)

-x 将变量声明为环境变量

-p 显示指定变量的被声明类型

#!/bin/bash
# 数值运算

aa=11
bb=22
declare -i cc=$aa+$bb
echo $cc

方法二 expr或let数值运算工具

#!/bin/bash
# 使用expr工具进行数值运算

aa=11
bb=22
dd=$(expr $aa + $bb)  #注意"+"左右两边有空格
echo $dd

方法三 $((运算式))或者$[运算式]

ff=$(($aa + $bb)) 注意在$aa$bb两边加上空格

2.2 变量测试和内容替换

对于两个变量x和y,测试y的值然后对x赋值(其实可以通过if实现同样的功能)

由于那个表格过于复杂,所以就不详细记录了,形如下面两个

x=${y-新值}

x=${y:-新值} 之类的语法,就是实现变量测试的功能

3. 环境变量配置文件

3.1 什么是 环境变量配置文件

环境变量-配置文件

环境变量是可以在父shell和子shell都生效的变量,Linux允许把本地变量声明为环境变量,但是不会永久生效,一旦重启,就会失效

想要永久生效,需要把这个更改放进 环境变量配置文件

环境变量配置文件中主要是 定义 对系统的操作环境生效的 系统默认环境变量,比如PATH,HISTSIZE(历史命令保存条数), PS1(提示符),HOSTNAME(主机名)等默认环境变量

source 命令

source 配置文件 配置文件生效需要重启,使用source命令可以直接强制更改生效

. 配置文件 注意.后面有空格,.source命令的缩写

3.2 环境变量配置文件作用

系统中默认的环境变量配置文件

/etc/profile

/ect/profile.d/*.sh

~/.bash_profile

~/.bashrc

/etc/bashrc

写在/etc目录下的文件 对所有用户生效

写在 ~ (家目录)下的文件只对当前用户生效

配置文件有优先级,登录后首先读取/ect/profile,该文件的作用:

  • USER变量
  • LOGNAME变量
  • MAIL变量
  • PATH变量
  • HOSTNAME变量
  • HISTSIZE变量
  • umask
  • 调用/etc/profile.d/*.sh文件

3.3 其他配置文件和登录信息

  1. 注销时生效的环境变量配置文件 ~/.bash_logout

  2. 历史命令的保存文件 ~/bash_history

  3. Shell登录信息 文件

    本地登录欢迎信息文件: /etc/issue

    转义符 略

    远程登录欢迎信息文件: /etc/issue.net

    这个是纯文本文件,不能转义

    登陆后欢迎信息: /etc/motd

    不管是本地登录,还是远程登录,都可以显示欢迎信息

4. 条件判断

4.1 按照文件类型进行判断

测试选项 作用
-d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真)
-e 文件 判断该文件是否存在(存在为真)
-f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真)

两种判断格式

使用test命令

一个例子 test -e /root/install.log 判断/root下是否有install.log

使用中括号 []

[ -e /root/install.log ] 请注意命令两边距离中括号有空格

如何查看判断结果? ->使用echo $?命令

但是这样是不是稍微显得有一些麻烦,如何解决这个问题?

[ -d /root ] && echo "yes" || echo "no" 第一条命令如果正确执行,则打印 yes,否则打印 no

4.2 按照文件权限进行判断

测试选项 作用
-r 判断文件是否存在,并且是否该文件拥有读权限
-w 判断该文件是否存在,并且该文件是否拥有写权限
-x 判断该文件是否存在,并且是否该文件拥有执行权限

4.3 两个文件之间进行比较

测试选项 作用
文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新
文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧
文件1 -ef 文件2 判断文件1和文件2的Inode号是否一致,可以理解为两个文件是否为同一个文件

4.4 两个整数之间的比较

测试选项 作用
整数1 -eq 整数2 判断整数1与整数2是否相等
整数1 -ne 整数2 判断两个整数是否不相等
整数1 -gt 整数2 整数1是否大于整数2
整数1 -lt 整数2 小于
整数1 -ge 整数2 大于等于
整数1 -le 整数2 小于等于

一个例子 [ 22 -gt 23 ] && echo yes || echo no

表示如果22>23则返回yes否则返回no

结果是no

4.5 字符串的判断

测试选项 作用
-z 字符串 判断字符串是否为空 (为空返回为真)
-n 字符串 判断字符串是否为非空(非空返回真)
字符串1==字符串2 判断字符串1是否和字符串2相等(相等返回为真)
字符串1!=字符串2 判断字符串2是否和字符串2不相等(不相等返回为真)

一个例子 [ -z "$name" ] && echo yes || echo no

如果name没有赋值,返回为yes,如果为name赋值,则返回no

4.6 多重条件判断

测试选项 作用
判断1 -a 判断2 逻辑与,判断1与判断2都成立,最终结果为真
判断1 -o 判断2 逻辑或,判断1与判断2有一个成立,返回结果为真
! 判断 逻辑非

输入命令的时候 注意空格

aa=11
[ -n "$aa" -a "$aa" -gt 23 ] && echo yes || echo no
# -n "$aa" 判断变量aa的是否有值,同时判断变量aa是否大于23
# 因为变量aa的值不大于23,所以第一个判断为真,但是逻辑与要求均为真,所以最后返回结果为假

5. 流程控制

5.1 if语句

1. 单分支if条件语句

if [ 条件判断式 ] ; then

	程序

fi

或者

if [ 条件判断 ]
	then
		程序
fi

注意:

  • 以if开头,以fi结尾,和其他语言不同
  • [ 条件判断式 ] 就是使用test命令判断,所以中括号和条件判断式之间必须有空格
  • then后面跟符合条件之后执行的程序,可以放在[]之后,用;分割,也可以换行写入,就不需要;

例子:判断分区使用率

#!/bin/bash

rate=$(df -h | grep "/dev/vda2" | awk '{print $5}' | cut -d "%" -f1)
# 把根分区使用率作为变量值赋予变量rate

if [ $rate -ge 80 ]
	then 
		echo "Warning! /dev/vda2 is full!!! "
fi

2. 双分支if条件语句

if [ 条件判断式 ]
	then
		条件成立时,执行的程序
	else
		条件不成立时,执行的另一个程序
fi

3. 多分支if 语句

if [ 条件判断式1 ]
	then
		当判断1成立时,执行程序1
	elif [ 条件判断式2 ]
		then
			当条件判断式2成立时,执行程序2
	elif ...
	else
		当所有条件都不成立,最后执行此程序
fi

一个例子,体会多分支语句

#!/bin/bash
#判断用户输入的是什么文件
# 通过这个脚本体会多分支语句

read -p "Please input a filename: " file
#接受键盘的输入,并赋予变量file

if [ -z "$file" ]
#判断file是否为空
	then 
		echo "Error, please input a filename"
		exit 1
elif [ ! -e "$file" ]
#判断file的值是否存在
	then 
		echo "Your input is not a file!"
		exit 2
elif [ -f "$file" ]
#判断file的值是否为普通文件
	then 
		echo "$file is a regulare file"
elif [ -d "$file" ]
#判断file的值是否为目录文件
	then 
		echo "$file is a directory"
	else
		echo "$file is an other file"
fi

5.2 case语句 多分支判断语句

case语句和if...elif...else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系

case $变量名 in
	"值1")
	如果变量的值等于值1,则执行程序1
	;;
	"值2")
	如果变量的值等于值2,则执行程序2
	;;
	*)
	如果变量的值都不是以上的值,则执行此程序
	;;
esac

一个例子

#!/bin/bash
#判断用户的输入

read -p "Please choose yes/no: " -t 30 cho
case $cho in 
	"yes")
		echo "Your choose is yes!"
		;;
	"no")
		echo "Your choose is no!"
		;;
	*)
		echo "Your choose is error!"
		;;
esac

不得不说,这语法太奇怪了...

5.3 for循环

语法1

for 变量 in 值1 值2 值3...
	do
		程序
	done

一个例子

#!/bin/bash
#打印时间
for time in morning noon afternoon night
	do 
		echo "$time"
	done

还有一个例子

#!/bin/bash

cd /root/sh/
ls *.sh > ls.log

y=1
for i in $(cat ls.log)
	do
		echo $y
		y=$(( $y+1))
	done

语法2

for (( 初始值;循环控制条件;变量变化 ))
	do
		程序
	done

一个例子

#!/bin/bash
#从1加到100

s=0
for ((i=1;i<=100;i=i+1))
do
	s=$(( $s+$i ))
done
echo "The sum of 1+2+3+...100 is: $s"

这里面有一个例子 ->批量添加指定数量的用户,不过有些复杂,和我的目的无关了,就不写了

5.4 while循环与until循环

while循环

while循环是不定循环,也称作条件循环,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样

语法

while [ 条件判断式 ]
	do
		程序
	done

一个简单的例子

#!/bin/bash

i=1
s=0
while [ $i -le 100 ]
#如果变量i的值小于等于100,则执行循环
do
		s=$(( $s+$i ))
		i=$(( $i+1 ))
done
echo "The sum is: $s"

until循环

until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序,一旦循环条件成立,则终止循环

until [ 条件判断式 ]
	do
		程序
	done

标签:脚本,文件,aa,shell,变量,编程,echo,判断,环境变量
From: https://www.cnblogs.com/guanghui-hua/p/17994249

相关文章

  • 解决“yarn : 无法加载文件 C:\Users\quber\AppData\Roaming\npm\yarn.ps1,因为
    1、......
  • 解决使用PowerShell执行命令出现“因为在此系统上禁止运行脚本”的问题
    1、......
  • [转]TypeScript类型编程中的extends和infer示例解析
    转自;https://www.jb51.net/javascript/294261vgi.htm TypeScript类型编程中的extends和infer示例解析 −目录引文extends条件判断约束参数类型约束infer推导的局部变量类型类型转换infer组合使用ReturnTypeParameters引文在刚接触TypeScript的时候,......
  • (22)Powershell中的环境变量
    (22)Powershell中的环境变量本节介绍Powershell中环境变量的查看和使用,主要包括以下内容:为什么要设置环境变量。Powershell中环境变量的查看。Powershell中环境变量的更改。总结1.为什么要设置环境变量使用过Java语言的一定知道在安装完JDK之后要配置环......
  • (21)Powershell中的通配符
    (21)Powershell中的通配符1.使用通配符进行文件的模糊查找Powershell中的通配符可以实现模糊查找,也就是说可以对一组项(而不是单个项)进行查找。例如,如果想查找D:\MyPowerShell目录中所有扩展名为.ps1的文件,可以执行以下命令:PSC:\test>Get-ChildItemC:\test\*.ps1......
  • (20)Powershell中的特殊运算符
    (20)Powershell中的特殊运算符Powershell中除了常见的算术运算符,赋值运算符,比较运算符,位运算符,逻辑运算符,字符串的拆分和合并运算符,转义字符,还有一些特殊的运算符,这些特殊的运算符往往可以解决一些特殊的问题,比如执行运行命令,更改值的数据类型等。1.&(调用运算符)使用&(......
  • PARI/GP编程示例
    素材主要来自我在RosettaCode上贡献的PARI/GP代码目录default(realprecision,110)控制实数计算的有效位数default(parisize,"32M");增加PARI/GP申请的栈内存大小顺序结构、选择结构、循环结构for-loop中设置步长vector实现map操作格式化打印switch-casefor-eachonelist应该没有......
  • CSAPP学习笔记——Chapter12 并行编程
    CSAPP学习笔记——Chapter12并行编程并发编程有着其独特的魅力,之前接触cuda编程的时候,感受到一些,没想到书里还有相关的内容。今天我们主要围绕进程,I/O多路复用,线程三种并发的方式,介绍并发编程的相关概念。并最终拓展chapter11讲中的echo服务器,使其能够处理多个客户端的连接请求......
  • 再谈函数式编程:释放编程创造力
    当抽象程度足够高,编程就能接近数学的优雅。在“Go模板:用代码生成代码”一文中,谈到了生成器模式的实现。先Copy如下:生成器模式(Builder)假设我们要造一辆车,车有车身、引擎、座位、轮子。Go的生成器模式的代码是这样子的:packagemodelimport"fmt"typeChinaCarstruc......
  • start cmd or shell from current directory in windows file explorer
    startwindowscmdincurrentdirectoryMypreferanceofstartingcmdinacertaincertaindirectoryissimplynavigatingtothedirectroy;pressingctrl+Ltofocustheaddressbar;typingcmd+enter.Bythisway,anewconsolewindowwillstartandit......