shell变量玩法详情

shell变量

1、变量的含义

记录事务的状态;
变就是事务的状态是会发生变化的;

变量本质是计算机中一种存、取数据的机制;
变量的数据都直接存储在内存中;

为什么要有变量?
因为程序的本质就是数据的不断变化,存取;
计算机程序的本质
程序=数据+算法(逻辑功能)

程序执行的本质就是一系列状态的变化,变是程序执行的直接体现;
所以我们需要有一种机制能够反映或者说是保存下来程序执行时状态以及状态的变化。
(例如一个变量,原本值是空字符串,接收用户输入的数据后,就存储了用户的数据)
shell变量
变量在每一种变量语言中都会用到;
shell也不例外,shell变量用于存、取数据,便于后续的反复使用。

2、变量的分类

环境变量(全局变量) 系统中全局生效的变量;
普通变量(局部变量)只对局部环境,如当前某一个login.sh脚本生效;

变量生命周期
1. 永久变量,写入文件,反复读取,加载,让其永久生效,如/etc/profile的PATH修改;
2. 临时变量,如命令行export定义一个变量存储数据,关闭shell会话后失效;

添加export变量

临时变量,是否添加export的区别
1、不加export,只对当前shell生效,子shell看不到
2、加export,当前shell会话进程,父子shell都可以用;
下载pstree
yum -y install psmisc

临时变量是否添加export的区别
1、不加export,只对当前shell生效,子shell看不到
[root@bogon    Wed Jun 22 12:33:57   
 ~]# pstree -p |grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)-+-grep(2267)
父进程
[root@bogon    Wed Jun 22 12:34:01   
 ~]# name=我是临时的
[root@bogon    Wed Jun 22 12:36:17   
 ~]# echo $name
我是临时的
子进程
[root@bogon ~]# echo $name

[root@bogon ~]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)---bash(2330)-+-grep(2344)
[root@bogon ~]# name=我是子shell
[root@bogon ~]# echo $name
我是子shell


添加进全局变量
[root@bogon    Wed Jun 22 13:34:59   
 ~]# tail -1 /etc/profile
export name2=我是永久变量
[root@bogon    Wed Jun 22 13:35:10   
 ~]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)-+-grep(3961)
[root@bogon    Wed Jun 22 13:35:24   
 ~]# echo $name2

[root@bogon    Wed Jun 22 13:35:36   
 ~]# so
soelim   sort     sotruss  source   
[root@bogon    Wed Jun 22 13:35:36   
 ~]# source /etc/profile
[root@bogon    Wed Jun 22 13:36:07   
 ~]# echo $name2
我是永久变量
[root@bogon    Wed Jun 22 13:36:11   
 ~]# bash
[root@bogon ~]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)---bash(3977)-+-grep(3989)
[root@bogon ~]# echo $name2
我是永久变量

父子进程

总结

1. 执行一次bash,就单独开辟一个子bash环境

2. 执行一次exit就退出一个bash环境

3. linux中提供了多种运行脚本的方式,区别在于,父子shell的创建


开启子bash的执行方式
[root@bogon    Wed Jun 22 13:46:34   
 ~]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)-+-grep(3999)
当前第一个父亲bash是2228
打印当前id的玩法

[root@bogon    Wed Jun 22 13:50:59   
 /tist_shell]# tail -3 id.sh 
echo "当前脚本执行的进程id是 $$"
exit 0

[root@bogon    Wed Jun 22 13:51:05   
 /tist_shell]# bash id.sh 
当前脚本执行的进程id是 4011


如果用source会直接退出
因为结尾的 exit 0,直接使用bash命令运行脚本,会额外创建一个子bash去运行脚本,而source则是当前进程去执行,所以会断开

[root@bogon    Wed Jun 22 13:53:50   
 /tist_shell]# bash id.sh 
当前脚本执行的进程id是 4012
[root@bogon    Wed Jun 22 13:53:51   
 /tist_shell]# vim id.sh 
[root@bogon    Wed Jun 22 13:54:07   
 /tist_shell]# tail -2 id.sh 
echo "当前脚本执行的进程id是 $$"

[root@bogon    Wed Jun 22 13:54:16   
 /tist_shell]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)-+-grep(4017)
[root@bogon    Wed Jun 22 13:54:31   
 /tist_shell]# source id.sh 
当前脚本执行的进程id是 2228

加入结尾的exit 0
[root@bogon    Wed Jun 22 13:54:38   
 /tist_shell]# vim id.sh 
[root@bogon    Wed Jun 22 13:55:20   
 /tist_shell]# pstree -p | grep ssh
           |-sshd(1153)---sshd(2224)---bash(2228)-+-grep(4021)
[root@bogon    Wed Jun 22 13:55:24   
 /tist_shell]# source id.sh 
当前脚本执行的进程id是 2228
Connection closing...Socket close.

Connection closed by foreign host.

Disconnected from remote host(192.168.1.104:22) at 13:55:28.

Type `help' to learn how to use Xshell prompt.
[D:\~]$ 

[root@bogon    Wed Jun 22 13:59:40   
 /tist_shell]# . id.sh 
当前脚本执行的进程id是 4027
Connection closing...Socket close.

Connection closed by foreign host.

Disconnected from remote host(192.168.1.104:22) at 13:59:54.

Type `help' to learn how to use Xshell prompt.
[D:\~]$ 

总结
source和.点的运行,都是不开启子bash,直接在当前bash中运行程序

加载环境变量文件的顺序

1. 登录ssh会话后,要加载/etc/profile
2. 执行用户家目录中的环境变量文件配置文件 ~/.bash_profile
3. 执行 ~/.bashrc
4. 执行/etc/bashrc

你以后可能会给系统定义很多变量

至少如你会修改PATH变量,添加你自己安装的软件路径想每次加载,在任何环境中这个PATH都是生效的


1.写入最优先级加载的/etc/profile

2.写入export PATH="xxxxxxxx"

3.这就会导致,无论你用哪个用户登录系统,或者进入任意的子bash环境都可以读取这个变量的值。

变量规范写法

变量由三大部分组成
1. 变量名,用于访问变量值的入口
2. 赋值符号,将内存中的数据,绑定到变量名
3. 变量值,具体的内存中数据

赋值变量符号左右,不能有空格,这是shell的要求
name=“阿飞”

变量命名规范

目的
1.存储数据,通过变量名提取

2.要不断的基于变量名,修改变量值,读取变量值。
规范
# 变量名的命令应该见名知意,同时遵循如下规则
以字母或下划线开头,剩下的部分可以是:字母、数字、下划线,最好遵循下述规范:
    1.以字母开头
    2.使用下划线做单词的连接
    3.同类型的用数字区分
    4.对于文件名的命名最好在末尾加上拓展名
    5.注意,变量名=变量值,等号两边没有空格;
    6. 系统默认使用的变量,基本是完全大写的变量名;

例如: sql_bak.tar.gz,log_bak.tar.bz2  
    5、不要带有空格、?、*等特殊字符 
    6、不能使用bash中的关键字,例如if,for,while,do等,如定义ls="大傻春醒醒"
    7、不要和系统环境变量冲突,如覆盖PATH,错误。


变量参考写法
纯字母:name
全小写:my_name
驼峰法:My_Name
全大写:MY_NAME

3、变量实际使用

字符串变量值

定义
[root@bogon    Wed Jun 22 14:12:18   
 ~]# name=afei
[root@bogon    Wed Jun 22 14:12:24   
 ~]# age=21
[root@bogon    Wed Jun 22 14:12:29   
 ~]# url="www.afeitt.cn"
[root@bogon    Wed Jun 22 14:12:44   
 ~]# echo $name $age $url
afei 21 www.afeitt.cn
[root@bogon    Wed Jun 22 14:13:03   
 ~]# echo ${name} ${age} ${url}
afei 21 www.afeitt.cn

命令定义变量

变量存储机器ip
[root@bogon    Wed Jun 22 14:15:04   
 ~]# local_ip="$(ifconfig ens33 |awk 'NR==2{print $2}')"
[root@bogon    Wed Jun 22 14:15:14   
 ~]# echo $local_ip 
192.168.1.104

变量存储主机名
[root@bogon    Wed Jun 22 14:15:04   
 ~]# local_ip="$(ifconfig ens33 |awk 'NR==2{print $2}')"
[root@bogon    Wed Jun 22 14:15:14   
 ~]# echo $local_ip 
192.168.1.104

时间
[root@bogon    Wed Jun 22 14:16:21   
 ~]# Now_Time=$(date +%F)
[root@bogon    Wed Jun 22 14:16:52   
 ~]# echo $Now_Time 
2022-06-22

命令定义变量的两个方式
1. 反引号、$(命令执行) 都可以将结果赋值给变量
2.  建议用$(),否则太多引号,容易搞混;

打印变量

${}更能恒昊的设置边界
[root@bogon    Wed Jun 22 14:18:35   
 ~]# echo $name
afei
[root@bogon    Wed Jun 22 14:18:40   
 ~]# echo $name_123

[root@bogon    Wed Jun 22 14:18:48   
 ~]# echo ${name}_123
afei_123


特殊情况,如设置百分比,建议这样用
[root@bogon    Wed Jun 22 14:18:54   
 ~]# progress="70"
[root@bogon    Wed Jun 22 14:20:16   
 ~]# echo "当前进度是${progress}%"
当前进度是70%

单双引号的坑
[root@bogon    Wed Jun 22 14:21:28   
 ~]# echo 打印我的名字:${name}
打印我的名字:afei
[root@bogon    Wed Jun 22 14:21:59   
 ~]# echo "打印我的名字:${name}"
打印我的名字:afei
[root@bogon    Wed Jun 22 14:22:09   
 ~]# echo '打印我的名字:${name}'
打印我的名字:${name}

结论
1. 单引号,原样输出
2. 双引号、可以解析变量

1. 你确认要提取变量的值,就双引号
2. 你确认必须要原样输出,是一个普通的字符串,或者显示特殊字符,就用单引号、或者反斜线  \   ,这个撬棍。

修改、删除变量

[root@bogon    Wed Jun 22 14:31:18   
 ~]# echo ${name}
afei
[root@bogon    Wed Jun 22 14:31:30   
 ~]# unset name
[root@bogon    Wed Jun 22 14:31:39   
 ~]# echo ${name}


查找变量
[root@bogon    Wed Jun 22 14:31:42   
 ~]# set |grep "^name"
name2=我是永久变量

修改,重新定义
[root@bogon    Wed Jun 22 14:31:42   
 ~]# set |grep "^name"
name2=我是永久变量
[root@bogon    Wed Jun 22 14:32:58   
 ~]# name2=海绵
[root@bogon    Wed Jun 22 14:34:08   
 ~]# set |grep "^name"
name2=海绵

显示的是数字类型值的变量(字符串)

[root@bogon    Wed Jun 22 14:35:19   
 ~]# age="20"
[root@bogon    Wed Jun 22 14:35:29   
 ~]# echo $age
20
[root@bogon    Wed Jun 22 14:35:38   
 ~]# # 在shell中,都是当做字符串去处理的,其他编程语言有明确的数据类型区别

4、变量传递,参数传递

变量除了在命令行直接调用、存、取值。

还经常用在脚本传递的参数中,但是脚本接收的参数,这个特殊变量,是shell内置固定的语法规则。
# 执行脚本,获取传入的位置参数,如 ./vars.sh af1 af2 af3 af4 af5 af6 af7
# 通过$n 获取第n个位置的参数值,从10开始,必须使用${n}不得简写
# shell变量的花式玩法

[root@bogon    Wed Jun 22 14:44:44   
 /tist_shell]# tail -21 var.sh 
#!/usr/bin/env bash
echo "当前shell脚本文件名:$0"
echo "第1个传入位置参数:$1"
echo "第2个传入位置参数:$2"
echo "第3个传入位置参数:$3"
echo "第4个传入位置参数:$4"
echo "第5个传入位置参数:$5"
echo "第6个传入位置参数:$6"
echo "第7个传入位置参数:$7"
echo "第8个传入位置参数:$8"
echo "第9个传入位置参数:$9"
echo "第10个传入位置参数:${10}"
echo "第11个传入位置参数:${11}"
echo "第12个传入位置参数:${12}"
echo "提取所有的位置参数,使用\$*提取:$*"
echo "提取所有的位置参数,使用\$@提取:$@"
echo "位置参数总个数是:$#"
echo "当前shell脚本执行的pid是:$$"
echo "上一个命令的执行返回结果是:$?"
exit 0


特殊变量的 $? 提取上一次命令执行结果

实战开发

[root@bogon    Wed Jun 22 15:12:11   
 /tist_shell]# cat user.sh 
#!/bin/bash
# 位置参数变量
username="${1}"
pwd="${2}"

# 创建用户
useradd ${username}

# 设置密码
echo ${pwd} | passwd --stdin ${username}

  1. 编写通过位置参数,自动修改主机名的脚本。
[root@bogon    Wed Jun 22 15:14:54   
 /tist_shell]# vim hostname.sh
[root@bogon    Wed Jun 22 15:15:40   
 /tist_shell]# bash hostname.sh  afei
当前主机名:afei
[root@bogon    Wed Jun 22 15:15:49   
 /tist_shell]# cat hostname.sh 
#!/bin/bash
# 位置参数变量
hostname=${1}

# 设置主机名
hostnamectl set-hostname ${hostname}

# 检查当前主机名
echo "当前主机名:$(hostname)"

5、交互式参数传递

利用read命令,接收用户输入,从键盘读取标准输入。

语法
read -p "提示信息" 变量名

用户信息接受

[root@bogon    Wed Jun 22 15:19:06   
 /tist_shell]# cat read.sh 
#!/bin/bash
# -s 不显示输入的内容,用于输入密码会用,保护密码
# -n 指定字符个数
# -t 输入超时时间


read -p "请输入账号:" username
read -s -t 20 -n 6 -p "请输入6为密码:" pwd
echo -e "\n================="
echo -e "\n账号是:${username}\n密码是:${pwd}"
[root@bogon    Wed Jun 22 15:19:14   
 /tist_shell]# bash read.sh 
请输入账号:afei
请输入6为密码:
=================

账号是:afei
密码是:111111

备份目录小脚本

[root@bogon    Wed Jun 22 15:24:31   
 /tist_shell]# cat backup.sh 
src_dir=/var/log/

# 让用户输入需要备份的目录
read -t 20 -p "请输入,你要备份的目的地:" backup_dir

echo "你输入的备份目录路径是:${backup_dir},开始备份中"
mkdir -p ${backup_dir} && cp -ar ${src_dir} ${backup_dir}

echo -e "查看备份目录信息:\n$(ls ${backup_dir})"



[root@bogon    Wed Jun 22 15:24:09   
 /tist_shell]# bash backup.sh 
请输入,你要备份的目的地:/backup
你输入的备份目录路径是:/backup,开始备份中
查看备份目录信息:
log

echo打印颜色(了解)

# 其中43的位置代表背景色, 30的位置是代表字体颜色
echo -e "\033[43;30m hello \033[0m"
echo -e "\033[31m hello \033[0m"
echo -e "\033[33m hello \033[0m"
echo -e "\033[41;33m hello \033[0m"
echo -e "\033[41;37m hello \033[0m"

面是相应的字和背景颜色,可以自己来尝试找出不同颜色搭配

例
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[41;33m 红底黄字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"

字颜色:30—–37
echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"

字背景颜色范围:40—–47
echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"
echo -e "\033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[0m"
echo -e "\033[44;37m 蓝底白字 \033[0m"
echo -e "\033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[0m"
echo -e "\033[47;30m 白底黑字 \033[0m"

最后面控制选项说明
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐

\033[30m — \33[37m

设置前景色
\033[40m — \33[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\33[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标
5参数为闪烁

用户输入综合小练习(实践)

第一种
cat >user_info.sh<<'EOF'
# 接收输入,保存变量
read -p "please input your name:" username
read -p "please input user uid:"  uid
read -p "please input your pwd:" pwd

# 使用变量,创建用户
useradd -u $uid $username
echo "$pwd" | passwd --stdin $username
echo "${username}:${pwd}" >> /tmp/user_info.glo

第二种
[root@bogon    Wed Jun 22 15:36:32   
 /tist_shell]# cat useradd.sh 

#!/usr/bin/env bash
echo "当前shell脚本文件名:$0"
echo "第1个传入位置参数:$1"
echo "第2个传入位置参数:$2"
echo "第2个传入位置参数:$3"

useradd -u $2 $1
echo "$3" | passwd --stdin $1
echo "$1:$3" >> /tmp/user_info.glo
exit 0

修改主机IP、主机名脚本(实践)

[root@bogon    Wed Jun 22 15:41:27   
 /tist_shell]# cat ip-hostname.sh 
# 拿到需求之后,分析,思考如何,提取主机名,修改主机名,结合变量,用户输入的玩法
# 别忘记变量定义的规范


# 1.接收用户输入的信息
read -p  "请输入要修改的主机名: "   new_hostname
read -p  "请输入要修改的IP地址: "   new_ip

# 2.替换用户输入
hostnamectl set-hostname ${new_hostname}
sed -i "/IPADDR/c IPADDR=${new_ip}" /etc/sysconfig/network-scripts/ifcfg-ens33

# 3.检查修改
echo -e "当前主机名是:\033[41;37m $(hostname) \033[0m"
echo -e "当前网卡配置文件内容是\n$(cat /etc/sysconfig/network-scripts/ifcfg-ens33 )

定时任务脚本

需求:通过交互式脚本,创建新的定时任务规则,要求

每十分钟和阿里云时间服务器同步。

# 思路
1. 先想好定时任务语句
2. 看要求,是交互式,还是非交互式
3. 如何写入定时任务规则

[root@bogon    Wed Jun 22 15:43:48   
 /tist_shell]# cat crontab.sh 
d -p "请输入crontab的时间频率:" cron_time
read -p "请输入crontab的具体命令:" cron_job

# 让用户输入生效
echo "#crontab by yuchao at $(date +%F)" >> /var/spool/cron/root
echo "$cron_time $cron_job" >> /var/spool/cron/root

echo -e "当前最新的计划任务是:\n$(crontab -l)"

[root@bogon    Wed Jun 22 15:47:12   
 /tist_shell]# bash crontab.sh 
请输入crontab的时间频率:*/2 * * * *
请输入crontab的具体命令:ntpdate -u ntp.aliyun.com
当前最新的计划任务是:
#crontab by yuchao at 2022-06-22
*/2 * * * * ntpdate -u ntp.aliyun.com

6、预定义变量

几个特殊的位置参数变量

$* 接收所有位置参数

$@ 接收所有位置参数

$# 参数个数

$$ 获取当前进程的PID

$? 上一个命令的返回值,0是正确,其他都错误(指的是你脚本上,查看$?的上一条命令)

测试预定义变量

[root@bogon    Wed Jun 22 16:05:26   
 /tist_shell]# cat ydy-vars.sh 
echo "提取所有的位置参数,使用\$*提取:$*"
echo "提取所有的位置参数,使用\$@提取:$@"
echo "位置参数总个数是:$#"
echo "当前shell脚本执行的pid是:$$"
echo "上一个命令的执行返回结果是:$?"

执行
[root@bogon    Wed Jun 22 16:05:24   
 /tist_shell]# bash ydy-vars.sh yy1 yy2 yy3 yy4
提取所有的位置参数,使用$*提取:yy1 yy2 yy3 yy4
提取所有的位置参数,使用$@提取:yy1 yy2 yy3 yy4
位置参数总个数是:4
当前shell脚本执行的pid是:4586
上一个命令的执行返回结果是:0

探测主机是否存活脚本

[root@bogon    Wed Jun 22 16:06:56   
 /tist_shell]# cat zj-ch.sh 
read -p "请输入需要探测的主机IP:" test_ip
ping -c 1 ${test_ip} &>/dev/null
if [ $? == 0 ];then
        echo "该机器${test_ip}运行正常。。。"
else
        echo "该机器${test_ip}已经挂了!!!"
fi
[root@bogon    Wed Jun 22 16:07:03   
 /tist_shell]# bash zj-ch.sh 
请输入需要探测的主机IP:192.168.1.104
该机器192.168.1.104运行正常。。。
[root@bogon    Wed Jun 22 16:07:25   
 /tist_shell]# bash zj-ch.sh 
请输入需要探测的主机IP:10.0.0.61
该机器10.0.0.61已经挂了!!!

获取所有位置参数(难点)

当我们想从脚本运行,传入的参数中获取具体的参数,可以用${n}

但是如果用户传入的参数不固定,你知道到底用 ${数字写多少合适?}

因此这时候,$* 和 $@ 的威力就来了,可以获取所有的位置参数(除了$0)

但是这俩变量虽说都是提取所有参数,但是提取之后的数据构造不一样,具体是什么,看于超老师给你演示一波。。
场景1,不加引号
1.当用户传入多个参数,都是以空格作为分隔符,获取每一个元素,此时$*和$@无区别。

2.注意此时,$*和$@ 这俩特殊变量,都没添加引号

[root@bogon    Wed Jun 22 16:22:58   
 /tist_shell]# cat all-vars.sh 
echo "----------------测试\$*,且无引号--------------"
for v in $*
do
    echo "传入的位置参数,分别是${v}"
done

echo "----------------测试\$@,且无引号--------------"
for v in $@
do
    echo "传入的位置参数,分别是${v}"
done

场景2,加上引号

1.此时用户传入的参数,比较特殊了,存在空格

2.因此你给特殊变量,加上引号,含义就不一样了!!
[root@bogon    Wed Jun 22 16:32:46   
 /tist_shell]# cat all2-vars.sh 
echo "----------------测试\$*,添加引号--------------"
for f in "$*"
do
    echo "传入的位置参数,分别是${f}"
done

echo "----------------测试\$@,添加引号--------------"
for f in "$@"
do
    echo "传入的位置参数,分别是${f}"
done

总结

"$*" 添加了引号的变量是: 将位置参数作为了一个大字符串整体,单个的参数。

"$@" 添加了引号的变量是: 依然是以空格区分位置参数

场景3,位置参数比较特殊

无引号

有引号的

总结

当你要将所有位置参数,多个参数,识别为一个整体,就用 "$*"

当你要单独的,提取为一个个参数,就用"$@" ,注意添加引号,否则没效果。

先记住语法,以后你会在高级脚本中,看到这个影子的。

7、常量

常量在shell中没有严格的语法支持,但是只有约定俗称的写法(全大写),以及通过命令强制性转为常量;
在其他数据类型更丰富的语言中,支持设定

普通变量,如name,age(如果age设置为常量,你理解下是什么意思,这种bug,常出现于初级开发的代码中。。)

常量,如月份,是固定的12个月,因此只能设定为无法修改的值,就是常量。

shell设置变量

通过readonly设置为常量。
[root@mapogo    Thu Jun 23 10:18:17   
 /]# grep -RI 'readonly' ./*

8.数据类型

数据类型的概念

数据就是指如变量的值,如web_site="www.yuchaoit.cn", 后面这个引号里的,就是数据,值。

变量是用来反应、保持数据的状态,以及变化的,并且生活里,除了文字,还有整数,小数,等丰富的数据类型,需要我们通过计算机程序去表示。

shell语言

shell是一个解释型、弱类型、动态语言;

shell变量的数据类型,由解释器在运行shell时,决定是什么数据类型。

bash中变量默认都是字符串类型,虽说都是字符串类型,但是分为如下几个场景
  • 数值
    • age=18
  • 字符串
    • name=yuchao
  • 数组
    • students=("张三" "李四" "于超")
  • 列表
    • {1..10}
shell比较特殊,不像其他编程语言,有明确的数据类型,是什么就是什么。
也就是,虽说有这些类型的区分,但是shell都是当做字符串去存储。

如
name="yuchao"
age=18

这俩变量的值都被shell以字符串形式在内存中存储了,但是age的值是数字,它是可以计算的。
编译型解释型
编译型的golang,需要go build
解释型的python,shell,需要用解释器执行代码
强类型、弱类型
强类型的golang,定义变量,以及数据类型,需要如下

var name string = "yuchao666"


----------------------------------------------------------------------------
弱类型的python,无须提前写好变量的类型

name = "yuchao666"  # 注意有空格

----------------------------------------------------------------------------
弱类型的shell,无须提前写好变量的类型
name="yuchao666"  # 注意无空格

----------------------------------------------------------------------------
因此强类型语言,定义变量,存储的数据,必须声明好它的类型,到底是string,还是int,还是floot

而弱类型的语言,数据类型是可以被忽略的,且修改变量的值之后,数据类型是可以随意切换的,没那么严格。

----------------------------------------------------------------------------

基本数据类型(shell中都以字符串对待)

数字
# int整型,存储如年龄、等级、身份证号、qq号、商品数量
age=10
level=3
qq_num=877348180
apple_count=9999999

----------------------------------------------------------------------------

# floot 浮点型,存储小数,如工资条,身高,体重
salary=8500.8
weight=175.53


----------------------------------------------------------------------------

数值类型变量支持的算术运算以及对应的算术运算符如下

加:+、+=、++
减:-、-=、--
乘:*、*=
除:/
取余 :%、%=

----------------------------------------------------------------------------


数值类型变量用于条件测试时支持的比较运算以及对应的运算符如下

等于:-eq
不等于:-ne
小于等于:-le
大于等于:-ge
大于:-gt
小于:-lt
逻辑与:&&
逻辑非:!
逻辑或:||

----------------------------------------------------------------------------


数值类型变量用于for循环时支持的比较运算以及对应的运算符如下

等于:==
不等于:!=
小于等于:<=
大于等于:>=
大于:>
小于:<
逻辑与:&&
逻辑非:!
逻辑或:||
字符串
# shell中,加了引号的就是字符串,但是shell比较特殊,默认都以字符串存储数据,因此字符串你可以省去引号,除非存在特殊符号,如空格等,必须加引号,否则有歧义。

如

[root@yuchaoit666 ~]#name=afei
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#name2="afei02"
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#name3="a fei"
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#echo $name $name2 $name3
afei afei02 a fei

----------------------------------------------------------------------------


# 结论
1. 不加引号的普通字符串,且是连续的字符(建议加引号,更规范)
2. 带有空格的,必须加引号
3. 单引号,双引号作用不一样。


----------------------------------------------------------------------------

单引号、双引号的区别
" " 弱引用,引号内加载特殊符号的作用
' ' 强引用,引号内的特殊字符全部取消意义

[root@yuchaoit666 ~]#name="afei"
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#echo "${name} is 666"
afei is 666
[root@yuchaoit666 ~]#echo '${name} is 666'
${name} is 666

9. 变量运算

变量运算语法

顾名思义,就是对变量计算数值计算,支持如下运算符。
数值类型变量支持的算术运算以及对应的算术运算符如下

加:+、+=、++
减:-、-=、--
乘:*、*=
除:/
取余 :%、%=

支持shell变量运算的里面

expr                 # 只支持整数运算
$(( ))             # 双括号运算,只支持整数运算,效率更高
$[]                    # 整数运算,语法简洁
bc                    # 支持整数,小数点运算
awk                    # 支持整数,小数点运算
%                        # 取余运算
expr

纯数字写法

变量运算

$(( ))

纯数值计算

变量计算

$[]

纯数值计算

变量计算

let

bc

awk运算
awk调用shell变量是双引号+单引号,双引号是保证正确处理变量值的空格。
awk支持小数处理。

posted @ 2022-08-03 20:47  张开嘴  阅读(107)  评论(0编辑  收藏  举报