Shell编程 - 变量篇
变量
1. 什么是变量
- 变量内存中的一块空间,变量名字 ==> 内存空间地址.
2. 变量命名规范
- 不能以数字开头。
- 不能以特殊符号开头,可以以"_"开头。
- 推荐字母开头
3. 变量的命名方式
- 驼峰方式: personOfName personOfAge
- ✔ 现代式: 单词(小写)+ "_下划线"连接 person_of_name
4. 环境变量相关文件及目录
文件或目录 | 应用场景 | |
---|---|---|
/etc/profile | 局生效(国法) 存放函数,环境变量。存放别名 | 要使用这个 |
/etc/bashrc | 全局生效(国法) 存放别名。 | |
~/.bashrc | 局部生效(家规) | |
~/.bash_profile | 局部生效(家规) | |
/etc/profile.d/ | 目录,每个用户登录的时候(远程连接与su切换),加载目录下面.sh结尾的文件. | 设置一些登录登录后提示,变化 |
案例01:书写脚本每次用户登录后显示系统的基本信息。⭐⭐
方法: 堆命令.
/etc/motd不行,输出固定的内容.
用户登录系统后,自动运行脚本./etc/profile.d/xxxx.sh结尾.
- 要求显示的内容与格式:
主机名:m01-shell
ip地址:10.0.0.61 172.16.1.61
总计内存:1.9G
可用内存:1.5G
系统负载:0.32, 0.23, 0.25 - 分析:
- 找出每个步骤对应的命令
- 创建变量,存放命令结果
- 把变量的结果输出
-
测试后放在/etc/profile.d/目录下.sh结尾
也可软链接到该目录下面 ln -s 源文件 目标文件
获取指标的命令。
主机名: hostname
ip地址: hostname -I
内存总数:free -h |awk 'NR
可用内存: free -h |awk 'NR
系统负载:uptime |awk '{print $(NF-2),$(NF-1),$NF}'
5. 系统变量
在命令行提示符直接执行env、set查看系统或环境变量。env显示用户环境变量,set显示Shell预先定义好的变量以及用户变量。可以通过export导出成用户变量。
一些写Shell脚本时常用的系统变量:
$SHELL | 默认Shell |
---|---|
$HOME | 当前用户家目录 |
$IFS | 内部字段分隔符 |
$LANG | 默认语言 |
$PATH | 默认可执行程序路径 |
$PWD | 当前目录 |
$UID | 当前用户ID |
$USER | 当前用户 |
$HISTSIZE | 历史命令大小,可通过HISTTIMEFORMAT变量设置命令执行时间 |
$RANDOM | 随机生成一个0至32767的整数 |
$HOSTNAME | 主机名 |
$$ | $$一个特殊的变量,它代表当前shell进程的PID |
6. 普通变量与临时环境变量
普通变量定义:VAR=value
临时环境变量定义:export VAR=value
变量引用:$VAR
Shell进程的环境变量作用域是Shell进程,当export导入到系统变量时,则作用域是Shell进程及其Shell子进程。
ps -axjf | grep pts命令的含义是:列出所有进程(包括没有控制终端的进程),
并以作业格式显示详细信息,然后通过grep过滤出包含“pts”的行。
这里的“pts”可能是指“pseudo-terminal slave”,即伪终端从设备,这通常与远程连接(如SSH)相关联。
ps:进程状态命令。
-a:显示所有终端的进程。
x:显示没有控制终端的进程。
-j:使用作业格式显示进程列表。
-f:全格式显示,包括更多详细信息。
|:管道符号,将前一个命令的输出作为后一个命令的输入。
grep:一个文本搜索工具,用于搜索包含特定模式的行。
pts:grep搜索的模式,用于匹配包含“pts”的行。
ps axjf输出的第一列是PPID(父进程ID),第二列是PID(子进程ID)
当SSH连接Shell时,当前终端PPID(-bash)是sshd守护程序的PID(root@pts/0),
因此在当前终端下的所有进程的PPID都是-bash的PID,比如执行命令、运行脚本。
所以当在-bash下设置的变量,只在-bash进程下有效,而-bash下的子进程bash是无效的,
当export后才有效。
所以在当前shell定义的变量一定要export,否则在写脚本时,会引用不到。
还需要注意的是退出终端后,所有用户定义的变量都会清除。
7. 特殊变量 - 位置变量
变量 | 含义 |
---|---|
$1-$n | 第一个到第n个变量 |
$0 | 脚本自身名字 |
$# | 位置参数总数 |
$@ | 每个位置参数被看做独立的字符串 |
$* | 所有的位置参数被看做一个字符串 |
- 位置变量指的是函数或脚本后跟的第n个参数。
- $1-$n,需要注意的是从第10个开始要用花括号调用,例如$
- shift可对位置变量控制,
#!/bin/bash
echo "1: $1"
shift
echo "2: $2"
shift
echo "3: $3"
# bash test.sh a b c
1: a
2: c
3:
每执行一次shift命令,位置变量个数就会减一,而变量值则提前一位。shift n,可设置向前移动n位。
8. 特殊变量 - 状态变量
变量 | 含义 |
---|---|
$? | 返回上一条命令是否执行成功,0为执行成功,非0则为执行失败 |
$$ | 当前进程PID |
$! | 上一条运行后台进程的PID |
案例02:执行脚本的时候输入用户名,判断用户名是否存在⭐⭐
- 分析:
- 命令行执行脚本的时候写上个用户名 sh user.sh kyle
- 脚本参数个数如果不是1,则输出使用帮助并退出脚本.
- 脚本运行的时候用户名被传递给id命令
- 判断 $?判断
#!/bin/bash
user=$1
#1. Determine if the user executing the script is root
if [ $UID -ne 0 ];then
echo "Please use the root to execute the script."
exit 0
fi
#2. The User Num
if [ $# -ne 1 ]
then
echo "Please enter a single user."
exit 0
fi
#3. Determine whether the user exists
id $user >/dev/null 2>&1
if [ $? -eq 0 ];then
echo "The user exist"
else
echo "The user does not exist; please create"
fi
******************************************************
$1 $# $? $UID
id 输出用的uid与gid
>/dev/null 2>&1 正确错误都定向到空 或者写成 &>/dev/null
-eq 等于 equal
-ne 不等于 not equal**
练一练
案例03-检查ip或域名是否可以访问脚本⭐⭐
- ping -c 次数 ip
- $?
9. 变量引用
- $与${}一致,可以用于取值。
- $变量
- ${变量} 指定变量名字
赋值运算符 | 含义 |
---|---|
= | 变量赋值 |
+= | 两个变量相加 |
- 自定义变量与引用
# VAR=123
# echo $VAR
123
# VAR+=456
# echo $VAR
123456
Shell中所有变量引用使用$符,后跟变量名。
有时个别特殊字符会影响正常引用,那么需要使用${VAR},例如:
# VAR=123
# echo $VAR
123
# echo $VAR_ # Shell允许VAR_为变量名,所以此引用认为这是一个有效的变量名,故此返回空
# echo ${VAR}
123
还有时候变量名与其他字符串紧碍着,也会误认为是整个变量:
# echo $VAR456
# echo ${VAR}456
123456
- 将命令结果作为变量值
# VAR=`echo 123`
# echo $VAR
123
# VAR=$(echo 123)
# echo $VAR
123
- 这里的反撇号等效于$(),都是用于执行Shell命令。
案例04:$n n大于9 会有什么问题?⭐⭐
$10
大于9后,会表示为$1 + 0 第1个参数+0
使用${}
案例05 书写一个回收站脚本,替代rm命令.⭐⭐
脚本要求
执行脚本传入参数被删除的文件或目录. sh 06.recyle_rm.sh /delete/ /tmp/delete.txt
检查脚本参数个数等于0则报错并退出.
脚本创建回收站目录mktemp命令创建临时目录 /recycle/随机目录(随机目录每次都是新的)/
把删除的文件或目录 移动 到这个临时目录中.
输出下临时目录名字和位置.
如何替代rm,通过alias替代,运行脚本sh 06.recyle_rm.sh
***************************************
mktemp -dp /recycle/ 在指定目录下面创建随机目录
默认创建随机文件,在/tmp/
-d创建随机目录
-p指定在哪个目录下面创建随机内容
-
配置别名用于替代rm
alias rm='sh /server/scripts/devopsshell/06.recyle_rm.sh'
10. 特殊变量-变量子串
变量子串 parameter表示变量名字 | 含义 |
---|---|
${parameter} $para | 变量取值 |
${#parameter} | 统计字符长度(变量中有多少个字符) |
删除(开头,结尾) | word表示要删除的内容 |
${parameter#word} | 从变量左边开始删除,按照最短(第1个)匹配删除 |
${parameter##word} | 从变量左边开始删除,按照最长(贪婪)匹配删除 |
${parameter%word} | 从变量右边开始删除,按照最短匹配删除 |
${parameter%%word} | 从变量左边开始删除,按照最长匹配删除 |
截取(切片) 类似于 cut -c | |
${var:5:2}. | 从下标是5字符开始向后截取2个字符 |
替换 阉割版的sed | |
${para/word/replace} | 把word替换为replace 仅替换第1个 |
${para//word/replace} | 把word替换为replace 全部替换 |
- 统计字符串长度
[root@web01 ~]# var=hello
[root@web01 ~]# echo $var
hello
[root@web01 ~]# echo ${#var}
5
案例 6 .I am oldboy teacher welcome to oldboy training class.⭐⭐
[root@web01 /service/scripts]# cat str.sh
#!/bin/bash
str=$*
new=`echo $str | sed 's#\.##g' `
echo $new
for i in $new
do
if [ ${#i} -le 6 ];then
echo $i
fi
done
[root@web01 /service/scripts]# bash str.sh I am English teacher welcome to training class.
I am English teacher welcome to training class
I
am
to
class
[root@web01 /service/scripts]#
*****************
# eq
# ne
# lt less than <
# le less equal <=
# gt great than >
# ge great equal >=
11. 变量赋值
- 变量赋值语句
- 向变量中写入内容。
直接赋值
var = hello 大部分时候使用
命令结果赋值
hostname=`hostname`获取命令的结果 或${}
脚本传参(通过脚本命令行传参进行赋值)
user_name=$1 脚本的第1个
参数
usernames="$*" 一般用于命令行内容传入脚本中. 不想设置太多交互.
read交互式赋值通过read命令实现与用户有个交互过程.
读取文件内容赋值给变量未来循环中说脚本读取文件的时候使用.
- read
参数 | 含义 |
---|---|
-p | 交互的时候提示信息 |
-t | 超过这个时间没有操作,则自动退出. |
-s | 不显示用户的输入.记录密码才用. |
- 基本用法
1. 显示用户的输入
read -p "请输入密码:" pass
请输入密码:*******'''
echo $pass
*******'''
2. 不显示用户的输入.
[root@web01~]# read -s -p "请输入密码:"
pass
请输入密码:[root@web01 ~]#
3.同时向2个变量赋值。
read -p "请输入2个数字num1 num2:" num1 num2
请输入2个数字num1 num2:a b
赋值方式 | read | $1 $2 $* $@ |
---|---|---|
共同的 | 变量赋值 | 变量赋值 |
区别 | 与用户 交互 的地方(一问一答) | 命令行传参,命令行脚本后面指定. |
案例7. 书写脚本检查输入的域名(1个或多个)是否可以ping通(通过read方式实现)⭐⭐