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 其他配置文件和登录信息
-
注销时生效的环境变量配置文件
~/.bash_logout
-
历史命令的保存文件
~/bash_history
-
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