一.SHELL脚本中的变量
1.1.什么是变量
-
在编写程序时,通常会遇到被操作对象不固定的情况
-
我们需要用一串固定的字符来表示不固定的值这就是变量存在的根本意义
-
变量的实现原理就是内存存储单元的一个符号名称
1.2.变量的命名规则
变量的名称中只能包含数字、大小写字母以及下划线 变量的名称只能用大小写字母及下划线开头 同一名称变量在多次被赋值时为覆盖动作 在企业代码规范化中变量的命名规则如下
简短全大写变量名 TIMINGLEE 首字母大写子类变量名 Timing_Lee 驼峰类型变量名: kuberneteS_Api
1.3.变量的调用方法
$aaa #表示取$aaa这个变量的值
[root@shell ~]# aaa=1
[root@shell ~]# echo $aaa
1
[root@shell ~]# echo ${aaa}B
1B
-
如果我们想表示1b
-
$aaab 这个变量调用方式是使用aaab这串字符变量的值
-
${aaa}b 如果需要在一串字符中特别说明那些字符表示变量那些字符不是,那么需 要用变量声明${}
-
-
查看系统中的所有变量可以使用 env
-
查看系统中所变量或函数可以使用set命令或declare
1.4.字符的转义及引用
-
在shell中有很多本身有特殊功能的字符,比如空格井号等等
-
如果在给变量赋值或执行命令使用时我们只想使用这些符号本身那么就需要用到转义或引用
-
在shell中反斜杠表示转义,每个反斜杠只能转义一个字符
-
在shell中单引号表示强引用,我们可以把它看作批量转义,在单引号内的所有字符被视为字符本身
-
在shell中双引号表示弱引用,其和单引号的区别在于不能引用(` \ ! $) 代码示例如下
[root@shell mnt]# echo \#hello
#hello
[root@shell mnt]# echo \# #hello
#
[root@shell mnt]# echo \# \#hello
# #hello
[root@shell mnt]# echo "# #"
# #
[root@shell mnt]# echo "$5"
[root@shell mnt]# echo '$5'
$5
1.5.变量的类型
从变量的作用范围来划分,变量分为函数级变量,环境级变量,用户级变量和系统级变量 函数级变量只在函数内生效通常用local来定义
vim aaa.sh
#!/bin/bash
ACTION () {
local a=1
echo $a
}
ACTION
echo $a
#sh test.sh
1
第二行显示为空
环境级别变量只在当前运行的shell中生效,shell关闭变量被释放
[root@shell mnt]# export B=2
[root@shell mnt]# vim aaa.sh
#!/bin/bash
TEXT()
{
local A=1
echo $A
}
TEXT
echo $B
[root@shell mnt]# sh aaa.sh
1
2
[root@shell mnt]# exit
logout
[root@shell mnt]# sh test.sh
显示为空
用户级变量只有登录系统的指定用户,此变量才生效
[root@shell mnt]# vim ~/.bash_profile
# User specific environment and startup programs
export B=2
[root@shell mnt]# sh -x aaa.sh
+ TEXT
+ local A=1
+ echo 1
1
+ echo 2
2
[root@shell ~]# su - wan
[wan@shell ~]$ sh /mnt/aaa.sh
显示为空
系统级变量是系统中的永久设定,所有用户都可以使用,系统变量通常被保存到/etc/profile中
[root@shell mnt]# vim /etc/profile.d/b.sh
#!/bin/bash
export B=2
[root@shell mnt]# source /etc/profile.d/b.sh
[root@shell mnt]# vim /mnt/aaa.sh
#!/bin/bash
echo $B
[root@shell mnt]# sh -x aaa.sh
+ TEXT
+ local A=1
+ echo 1
1
+ echo 2
2
在系统中通常设置系统变量是编辑文件更加安全 文件修改完毕后需要用source命令使其生效
1.6.常见的系统及变量
在系统中被预设的变量如下
变量 | 说明 |
---|---|
PATH | 命令的搜索路径,以冒号作为分隔符 |
HOME | 用户的家目录的路径,是cd命令的默认参数 |
COLUMNS | 命令行编辑模式下可使用命令的长度 |
HISTFILE | 命令历史的文件路径 |
HISTFILESIZE | 命令历史中包含的最大行数 |
HISTSIZE history | 命令输出的记录数 |
LOGNAME | USER 当前用户的名字 |
SHELL | 当前使用的shell |
PWD | 当前的工作目录 |
PS1 | 命令行提示符变量 |
PATH指定命令执行路径是非常有用 如果我想在当前用户中可以用相对路径方式调用/mnt下的所有可执行文件
[root@shell ~]# chmod +x /mnt/aaa.sh
[root@shell ~]# aaa.sh
bash: aaa.sh: 未找到命令...
[root@shell ~]# vim ~/.bash_profile
PATH=$PATH:/mnt
[root@shell ~]# source ~/.bash_profile
[root@shell ~]# aaa.sh
1
2
[root@shell ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
/mnt
1.7.特殊变量定义方式
1.7.1.用命令的执行结果定义变量
在执行命令时如果想让指定命令优先执行可以使用 $(cmd) 或 ``
[root@shell ~]# date +%m-%d_%H:%M
12-21_18:34
[root@shell ~]# touch file_$(date +%m-%d_%H:%M)
[root@shell ~]# ls
file_12-21_18:35
[root@shell ~]# touch file_`date +%m-%d_%H:%M` //反向单引号
[root@shell ~]# ls
file_12-21_18:35 file_12-21_18:38
1.7.2.传参变量
很多情况下,shell脚本需要接受用户的输入,根据用户的输入来执行不同的操作。 从命令行传递给shell脚本的参数又称为叫做位置参数,shell脚本会根据参数的位置使用不同的位置参数 变量读取他们的值
变量 | 说明 |
---|---|
$# | 命令行的参数的个数 |
$0 | 当前脚本的名称 |
$n | 当前传递给脚本的第n个参数,比如$1表示脚本的第一个参数,$2表示脚本的第二个参数…… |
$* | 以“参数1 参数2 参数3”的形式返回所有参数的值 |
$@ | 以“参数1” “参数2” “参数3” 的形式返回所有参数的值 |
[root@shell ~]# vim test.sh
#!/bin/bash
echo '$1' is $1
echo '$2' is $2
echo '$3' is $3
echo '$#' is $#
echo '$@' is $@
echo '$*' is $*
[root@shell ~]# sh aaa.sh a1 a2
$1 is a1
$2 is a2
$3 is
$# is 2
$* is a1 a2
$@ is a1 a2
[root@shell ~]# sh aaa.sh a1 a2 a3
$1 is a1
$2 is a2
$3 is a3
$# is 3
$* is a1 a2 a3
$@ is a1 a2 a3
$? 表示上一条命令的退出值,0表示无任何问题,1-255 表示命令执行报错
$$ 表示当前进程的pid
[root@shell ~]# echo $$
2617
[root@shell ~]# ps
PID TTY TIME CMD
2617 pts/0 00:00:00 bash
3469 pts/0 00:00:00 ps
[root@shell ~]# echo $?
0
[root@shell ~]# ls fff
ls: 无法访问 'fff': 没有那个文件或目录
[root@shell ~]# echo $?
2
1.7.3 交互式传参
利用read命令可以和脚本执行者进行交互传参 示例: 交互赋值单个变量
[root@shell ~]# read A
123
[root@shell ~]# echo $A
123
交互赋值多个变量
[root@shell ~]# read A B C
1 2 3
[root@shell ~]# echo $A $B $C
1 2 3
交互赋值数组
[root@shell ~]# read -a ddd
more less some none
[root@shell ~]# echo $ddd
more
[root@shell ~]# echo ${ddd[1]}
less
[root@shell ~]# echo ${ddd[2]}
some
[root@shell ~]# echo ${ddd[3]}
none
交互赋值并显示提示符
[root@shell ~]# read -p "Please input word:" A
Please input word:hello
[root@shell ~]# echo $A
hello
隐藏赋值内容
[root@shell ~]# read -p "Please input word: " -s A
Please input word: [root@shell ~]# echo $A
hello
设置超时时间
[root@shell ~]# read -t 5 -p "Please input word: " A
设置赋值长度
[root@shell ~]# read -n 3 -p "Please input word: " A
指定录入结束符
[root@shell ~]# read -d "." a
123456.
-a 读取的内容存入数组
-d 持续读取直到读入 DELIM 变量中的第一个字符,而不是换行符
-n/N 读取N个字符
-p 指定提示信息,用于等待输入
-r 不允许反斜杠转义任何字符
-s 从标准输入中读取密码而不在屏幕上显示输入的字符
-t 设置读取输入的超时时间,单位为秒
1.7.4 数组变量
我们可以定义变量为一组内容,中间的元素用空格隔开
A=(1 2 3 4 5)
取变量的所有元素
[root@shell ~]# echo ${a[*]}
1 2 3 4 5
[root@shell ~]# echo ${a[@]}
1 2 3 4 5
取数组的第一个元素
[root@shell ~]# echo ${a[0]}
1
取数组的最后一个元素
[root@shell ~]# echo ${a[-1]}
5
取数组的第1-3个元素
[root@shell ~]# echo ${a[*]:0:3}
1 2 3
查看数组的元素个数
[root@shell ~]# echo ${#a[@]}
5
管理数组元素
[root@shell ~]# a[0]=6 #更改数组第一个元素为6
[root@shell ~]# echo ${a[@]}
6 2 3 4 5
[root@shell ~]# a[5]=6 #添加数组中的第六个元素为6
[root@shell ~]# echo ${a[@]}
6 2 3 4 5 6
[root@shell ~]# unset a[0] #删除数组中第一个元素
[root@shell ~]# echo ${a[@]}
2 3 4 5 6
[root@shell ~]# unset a #删除整个数组
1.7.5.变量中字符串的取值管理
示例: 设定实验变量
[root@shell ~]# str="/more/less/some./no.ne"
取所有字符串
[root@shell ~]# echo ${str}
/more/less/some./no.ne
统计字符串长度
[root@shell ~]# echo ${#str}
22
从指定位置取值到结尾
[root@shell ~]# echo ${str:3}
re/less/some./no.ne
从指定位置取指定长度的字符
[root@shell ~]# echo ${str:2:4}
ore/
[root@shell ~]# echo ${str::4}
/mor
从倒数第3个字符向后取2个字符
[root@shell ~]# echo ${str:0-3:2}
.n
取最后5个字符
[root@shell ~]# echo ${str:0-5}
no.ne
从开头检索最近匹配字符串并删除
从先到后
[root@shell ~]# echo ${str#*/}
more/less/some./no.ne
从后到前
[root@shell ~]# echo ${str%%/*}
输出为空
从开头检索最远匹配字符串并删除
从前到后
[root@shell ~]# echo ${str##*/}
no.ne
从后到前
[root@shell ~]# echo ${str%/*}
/more/less/some.
输出为空替换字符
[root@shell ~]# echo ${str/./@} //默认替换第一个
/more/less/some@/no.ne
[root@shell ~]# echo ${str//./@} //替换所有
/more/less/some@/no@ne
1.7.5.脚本中的函数
变量是一个变化值的别名 函数就是一段程序的别名
1.解决代码重复问题
#!/bin/bash
echo -e "\033[31mread \033[0m"
echo -e "\033[32mgreen \033[0m"
echo -e "\033[33myellow \033[0m"
echo "====== function ============="
ECHO ()
{
echo -e "\033[$1m$2\033[0m"
}
ECHO 31 red
ECHO 32 green
ECHO 33 yellow
2.代码无线循环
#!/bin/bash
ACTION()
{
read -p "Please input word: " WORD
echo $WORD
ACTION
}
ACTION
1.8.取消变量
unset 变量 即可把变量取消
如果变量被记录到配置文件中需要在配置文件中删除记录
二.shell中的运算
2.1.shell中的运算命令
2.2.shell中的数学运算符号
shell中常用的运算符号如下:
2.3.位运算
2.3.1.什么是位运算
程序中的所有数在计算机内存中都是以二进制的形式储存的 位运算就是直接对整数在内存中的二进制位进行操作
2.3.2.二进制的的负数表示方法
2进制表示数字正负时最高位为0表示正数,最高位1表示负数 源码:负数的源码为负数绝对值的二进制数字,整数的源码为本身的二进制 反码:负数绝对值源码取反,但是表示正负的高位值不变 补码:反码+1为补码,补码即为负数二进制表示方式 计算结果超过8位舍弃超过的高位,特殊需要情况下使用扩展8位
1 的二进制源码 0000 0001
-1 的二进制原码 1000 0001
1 的反码 0000 0001
-1 的反码 1111 1110
1 的二进制码 0000 0001
-1 的二进制码 1111 1110+0000 0001 = 11111111
负数补码的原因是为了可以让加法器同时可以运算加法和减法 以时钟位例子 我想把8点调到10点: 顺时针8+2 逆时针8-10 最终时针的位置计算公式; 8+(顺时针调正的格数|神秘数字-逆时针调整的格子)=最终位置 神秘数字是时钟显示里最大数字+1
2.3.4位逻辑运算
[root@shell ~]# vim aaa
000001 1
000010 2
000100 4
001000 8
[root@shell ~]# echo $((2<<1))
4
[root@shell ~]# echo $((2>>1))
1
[root@shell ~]# echo $((4<<1))
8
[root@shell ~]# echo $((4<<2))
16
[root@shell ~]# echo $((4<<3))
32
[root@shell ~]# a=10
[root@shell ~]# echo $((a<<1))
20
[root@shell ~]# echo $((a<<2))
40
[root@shell ~]# echo $((a<<3))
80
[root@shell ~]# a=5
[root@shell ~]# echo $((a<<1))
10
[root@shell ~]# echo $((a<<2))
20
[root@shell ~]# echo $((a<<3))
40
[root@shell ~]# echo $((1&2))
0
[root@shell ~]# echo $((1|2))
3
[root@shell ~]# echo $((1^2))
3
[root@shell ~]# echo $((~1))
-2
[root@shell ~]# a=1
[root@shell ~]# ((a&=2))
[root@shell ~]# echo $a
0
[root@shell ~]# a=1
[root@shell ~]# ((a|=2))
[root@shell ~]# echo $a
3
[root@shell ~]# a=1
[root@shell ~]# ((a^=2))
[root@shell ~]# echo $a
3