兄弟连linux基础之Shell基础(三)——Bash的变量及运算

视频参考:https://www.bilibili.com/video/BV1mW411i7Qf?from=search&seid=11812550775556654179

一、用户自定义变量

1、什么是变量

变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字 ,所以很容易引用它。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。

2、变量设置规则

  • 变量名称可以由字母、数字和下划线组成 ,但是不能以数字开头。如果变量名是 “2name”则是错误的。
  • 在Bash中,变量的默认类型都是字符串型 ,如果要进行数值运算,则必修指定变量类型为数值型。
  • 变量等号连接值,等号左右两侧不能有空格,eg…name=xdl。 
  • 变量的值如果有空格,需要使用单引号或双引号包括,eg…name=‘x d l’。 
  • 变量的值中,可以使用“\”转义符。 
  • 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含 “$变量名”或用${变量名}包含。
  • 如果是把命令的结果作为变量值赋予变量 ,则需要使用反引号或$()包含命令。
  • 环境变量名建议大写,便于区分。

3、变量分类

  • 用户自定义变量
  • 环境变量:这种变量中主要保存的是和系统操作环境相关的数据。系统已有的变量名可以更改其值,用户也可以自定义新的变量名。 
  • 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的,但是变量值可以更改,是预定义变量的一种。
  • 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的,但是变量值可以更改。

4、本地变量(用户自定义变量)

ly2@DGX:$ aa=123   # 变量定义
ly2@DGX:$ bb=xdl
ly2@DGX:$ echo $aa   # 变量调用,用echo+$查看
123
ly2@DGX:$ echo $bb
xdl
ly2@DGX:$ aa="$aa"456  # 变量叠加方法1 
ly2@DGX:$ echo $aa     # 叠加变量输出
123456
ly2@DGX:$ aa=${aa}789   # 变量叠加方法2
ly2@DGX:$ echo $aa     # 叠加变量输出
123456789
ly2@DGX:$ set      # 查看所有变量
ly2@DGX:$ unset aa  # 变量删除 

二、环境变量

1、环境变量是什么

  • 用户自定义变量只在当前的Shell中生效。
  • 而命令行的环境变量会在当前Shell和这个Shell的所有子Shell当中生效。
  • 如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的Shell中生效。

2、设置环境变量

ly2@DGX:~$ bash      # 新建一个bash的子shell
ly2@DGX:~$ pstree    # 以树形结构显示程序和进程之间的关系,即哪个进程是父进程,哪个是子进程
temd─┬─NetworkManager─┬─{gdbus}
        │                └─{gmain}
        ├─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─cachefilesd
        ├─cron
        ├─dbus-daemon
        ├─2*[dhclient]
        ├─fail2ban-server───2*[{fail2ban-server}]
        ├─gdm3─┬─{gdbus}
        │      └─{gmain}
        ├─login───bash
        ├─polkitd─┬─{gdbus}
        │         └─{gmain}
        ├─rsyslogd─┬─{in:imklog}
        │          ├─{in:imuxsock}
        │          └─{rs:main Q:Reg}
        ├─smartd
        ├─sshd─┬─2*[sshd───sshd───bash]
        │      ├─sshd───sshd───bash───jupyter-noteboo─┬─python───8*[{python}]
        │      │                                      └─2*[{jupyter-noteboo}]
        │      ├─2*[sshd───sshd───2*[sftp-server]]
        │      ├─sshd───sshd─┬─python3───62*[{python3}]
        │      │             ├─python3───61*[{python3}]
        │      │             └─sftp-server
        │      ├─sshd───sshd───bash───bash───pstree  # 远程连接ssh,一个父进程bash,一个子进程bash
        │      ├─2*[sshd───sshd───bash───su───bash]
        │      ├─sshd───sshd───bash───python─┬─python
        │      │                             └─168*[{python}]
        │      └─sshd───sshd───bash───2*[python─┬─python]
        │                                       └─168*[{python}]]
        ├─4*[systemd───(sd-pam)]
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-timesyn───{sd-resolve}
        └─systemd-udevd
ly2@DGX:~$ exit    # 退出子shell
exit
ly2@DGX:~$ export my_name=len  # 新建(声明)环境变量,export 变量名=变量值
ly2@DGX:~$ your_name=qwe       # 新建(声明)本地变量,变量名=变量值
ly2@DGX:~$ set | grep "my_name"     # 搜索环境变量
my_name=len                         # 输出环境变量
ly2@DGX:~$ set | grep "your_name"       # 搜索本地变量
your_name=qwe                           # 输出本地变量
ly2@DGX:~$ bash           # 新建子shell
ly2@DGX:~$ set | grep "my_name"     # 搜索环境变量      
my_name=len                         # 输出环境变量
ly2@DGX:~$ set | grep"your_name"        # 搜索本地变量
grepyour_name: command not found        # 输出本地变量
ly2@DGX:~$ env    # 查询所有环境变量
XDG_SESSION_ID=52     #输出所有环境变量
TERM=xterm
…………
PWD=/home/ly2
my_name=len           # 自定义的环境变量
LANG=en_US.UTF-8
…………
ly2@DGX:~$ unset my_name   # 删除自定义环境变量 my_name
ly2@DGX:~$ env    # 查询所有环境变量       
…………
PWD=/home/ly2          # 自定义的环境变量已删除
LANG=en_US.UTF-8
…………

3、系统常见环境变量

  • PATH:系统查找命令的路径
ly2@DGX:~$ echo $PATH        # 可以看出系统路径以分号分隔
/home/ly2/bin:/home/ly2/.local/bin:/usr/local/cuda/bin:/opt/conda/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
ly2@DGX:~$ ls  # 输入ls时,系统将在以上路径中查找系统命令的可执行文件
hello.sh  miniconda3  Miniconda3-latest-Linux-x86_64.sh  tongpeifu

ly2@DGX:~$ chmod 755 hello.sh
ly2@DGX:~$ ./hello.sh
hello world

ly2@DGX:~$ cp hello.sh /bin/            # cp hello.sh ~/bin/可以?
cp: cannot create regular file '/bin/hello.sh': Permission denied  # ?
ly2@DGX:~$ hello.sh       # 这时可执行文件的命令可直接执行,做法不推荐
hello.sh: command not found  # ?

ly2@DGX:~$ PATH="$PATH":/hh       # PATH变量叠加
ly2@DGX:~$ echo $PATH       # 可以看到最后一个新添加的路径
/home/ly2/bin:/home/ly2/.local/bin:/usr/local/cuda/bin:/opt/conda/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/hh
ly2@DGX:~$ hello.sh        # 运行失败?
hello world
  • PS1:定义系统提示符的变量,只能用set查看。即ly2@DGX:~$,可以更改。
提示符 作 用
\d 显示日期,格式为“星期 月 日”
\h 显示简写主机名。如默认主机名“localhost”
\t 显示24小时制时间,格式为“HH:MM:SS”
\T 显示12小时制时间,格式为“HH:MM:SS”
\A 显示24小时制时间,格式为“HH:MM”
\u 显示当前用户名
\w 显示当前所在目录的完整名称
\W 显示当前所在目录的最后一个目录
\# 执行的第几个命令
\$ 提示符。如果是root用户会显示提示符为“#”,如果是普通用户会显示提示符为“$”
ly2@DGX:~$ echo $PS1
${debian_chroot:+($debian_chroot)}\u@\h:\w\$
ly2@DGX:~$ PS1='[\u@\t \w]\$'     # 设置系统提示符,当前用户名@24小时制 完整目录
[ly2@10:07:15 ~]$PS1='[\u@\t \w]\$ '   # \$后有空格
[ly2@10:07:25 ~]$ cd /usr/local/src     # 进入文件夹
[ly2@10:09:03 /usr/local/src]$ PS1='[\u@\h:\w]\$ '   # 显示完整路径
[ly2@DGX:/usr/local/src]$ PS1='[\u@\h:\W]\$ '
[ly2@DGX:/]$                    # 显示的不是 ~ ?,重启终端恢复正常

三、位置参数变量

1、位置参数变量

位置参数变量 作 用
$n n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10}。
$* 这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体
$@ 这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
$# 这个变量代表命令行中所有参数的个数
  • $n:把命令和命令之后的参数传递给脚本中的$n位置参数变量。
ly2@DGX:~/sh$ vim canshu1.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
ly2@DGX:~/sh$ chmod 755 canshu1.sh
ly2@DGX:~/sh$ ./canshu1.sh
./canshu1.sh                      # $0 执行命令其本身
                                  # $1 传递第一个参数,空                           
                                  # $2 传递第二个参数,空 
                                  # $3 传递第三个参数,空 
ly2@DGX:~/sh$ ./canshu1.sh 11 22 33      # 向脚本中传递所需数值
./canshu1.sh                      # $0 执行命令其本身
11                                # $1 传递第一个参数11
22                                # $2 传递第二个参数22
33                                # $3 传递第三个参数33
  • $n:求和运算,相当于计算器。
ly2@DGX:~/sh$ vim sum.sh
#!/bin/bash            # sum=$(($1 + $2)),省略赋值过程
num1=$1
num2=$2
sum=$(($num1 + $num2)) #变量sum的和是num1+num2
echo $sum  # 打印变量sum的值
ly2@DGX:~/sh$ chmod 755 sum.sh
ly2@DGX:~/sh$ ./sum.sh 11 22
33
  • 特殊符号$#,$*,$@
ly2@DGX:~/sh$ vim canshu2.sh
#!/bin/bash
echo $#             # 输出命令行中所有参数的个数
echo $*             # 输出命令行中所有的参数,整体
echo $@             # 输出命令行中所有的参数,区分                 
ly2@DGX:~/sh$ ./canshu2.sh 11 22 33 44 55 canshu
6
11 22 33 44 55 canshu
11 22 33 44 55 canshu

ly2@DGX:~/sh$ vim canshu3.sh
#!/bin/bash
echo "A total of $# parameters"
echo "The parameters is:$*"
echo "The parameters is:$@"
ly2@DGX:~/sh$ chmod 755 canshu3.sh
ly2@DGX:~/sh$ ./canshu3.sh 45 22 33 44 55 canshu
A total of 6 parameters
The parameters is:45 22 33 44 55 canshu
The parameters is:45 22 33 44 55 canshu
  • $*与$@的区别
ly2@DGX:~/sh$ vim canshu4.sh
#!/bin/bash
for i in "$*"
# $*中的所有参数看成是一个整体,所以这个for循环只会循环一次
    do
        echo "The parameters is:$i"
    done
x=1
for y in "$@"
# $@中的所有参数看成是独立的,所以“$@”中有几个参数,就会循环几次
    do
        echo "The parameters$x is:$y"
        x=$(($x+1))
    done
ly2@DGX:~/sh$ chmod 755 canshu4.sh
ly2@DGX:~/sh$ ./canshu4.sh 11 22 33 44
The parameters is:11 22 33 44
The parameters1 is:11
The parameters2 is:22
The parameters3 is:33
The parameters4 is:44

四、预定义变量

1、预定义变量

预定义变量 作 用
$? 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
$$ 当前进程的进程号(PID)
$! 后台运行的最后一个进程的进程号(PID)
  • $?:之前的逻辑与(&&),逻辑或(| |)就是通过($?)判断的
ly2@DGX:~/sh$ ls         # 正确命令执行
canshu1.sh  canshu3.sh  hello.sh   sum.sh   canshu2.sh  canshu4.sh
ly2@DGX:~/sh$ echo $?            # 返回0
0
ly2@DGX:~/sh$ lsafaf     # 错误命令执行
lsafaf: command not found
ly2@DGX:~/sh$ echo $?
127                             # 返回非 0,127
ly2@DGX:~/sh$ ls ad     # 查找不存在的文件
ls: cannot access 'ad': No such file or directory
ly2@DGX:~/sh$ echo $?           # 返回非 0,2
2
  • $$:进程号
ly2@DGX:~/sh$ vim canshu5.sh
#!/bin/bash
echo "The current process is $$"
# 输出当前进程的PID
# 这个PID就是当前这个脚本执行时,生成的进程的PID
find /home/ly2 -name hello.sh&
# 使用find命令在root目录下查找hello.sh文件
# 符号&表示把命令放入后台执行,工作管理在系统管理一章介绍
echo "The last one Daemon process is $!"

ly2@DGX:~/sh$ chmod 755 canshu5.sh
ly2@DGX:~/sh$ ./canshu5.sh
The current process is 45555           # 当前脚本执行的进程号
The last one Daemon process is 45556   # 最后运行程序的进程号
ly2@DGX:~/sh$ /home/ly2/sh/hello.sh   # 最后进程的输出结果,查找出的路径

2、接收键盘输入

[root@localhost ~]# read [选项] [变量名]
选项:
-p “提示信息”:在等待read输入时,输出提示信息
-t 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数:read命令只接受指定的字符数,就会执行
-s:隐藏输入的数据,适用于机密信息的输入

ly2@DGX:~/sh$ vim canshu6.sh
#!/bin/bash
read -t 30 -p "Please input your name: " name
# 提示 “请输入姓名”,并等待30秒,把用户的输入保存入变量name中
echo "Name is $name"         # 输出传入变量的值

read -s -t 30 -p "Please enter your age: " age
# 年龄是隐私,所以用“-s”选项隐藏输入
echo "\n"                      # 空出一行
echo "Age is $age"

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

ly2@DGX:~/sh$ chmod 755 canshu6.sh
ly2@DGX:~/sh$ ./canshu6.sh                 # 运行结果
Please input your name: as
Name is as
Please enter your age:
Age is 24
Please select your gender[M/F]: F
Sex is F

五、数值运算与运算符

1、declare声明变量类型

[root@localhost ~]# declare [+/-][选项] 变量名
选项:
-:给变量设定类型属性
+:取消变量的类型属性
-i:将变量声明为整数型(integer)
-x:将变量声明为环境变量
-p:显示指定变量的被声明的类型

ly2@DGX:~/sh$ aa=11          # 给变量 aa 和 bb 赋值
ly2@DGX:~/sh$ bb=22
ly2@DGX:~/sh$ cc=$aa+$bb
ly2@DGX:~/sh$ echo $cc       # shell中默认字符均为string
11+22
ly2@DGX:~/sh$ declare -p aa      # 查看变量 aa 的类型
declare -- aa="11"
ly2@DGX:~/sh$ export aa      # 将 aa 声明为环境变量
ly2@DGX:~/sh$ declare -p aa      # 查看变量 aa 的类型
declare -x aa="11"           # -x表示 aa 为环境变量

2、数值运算

  • 方法1:
ly2@DGX:~/sh$ declare -i cc=$aa+$bb   # 将变量 cc 声明为整数型
ly2@DGX:~/sh$ echo $cc
33
  • 方法2:expr或let数值运算工具(不推荐)
ly2@DGX:~/sh$ dd=$(expr $aa + $bb)   # 注意“ + ”号左右两侧必须有空格
ly2@DGX:~/sh$ echo $dd          
33
  • 方法3:“$((运算式))”或“$[运算式]”
ly2@DGX:~/sh$ ff=$(($aa+$bb))
ly2@DGX:~/sh$ echo $ff
33
ly2@DGX:~/sh$ gg=$[$aa+$bb]
ly2@DGX:~/sh$ echo $gg
33

3、运算符

  • 优先级由上至下逐渐降低:
优先级 运算符 说明
13 -, + 单目负、单目正
12 !, ~ 逻辑非、按位取反或补码
11 * , / , % 乘、除、取模
10 +, - 加、减
9 << , >> 按位左移、按位右移
8 < =, > =, < , > 小于或等于、大于或等于、小于、大于
7 == , != 等于、不等于
6 & 按位与
5 ^ 按位异或
4 | 按位或
3 && 逻辑与
2 | | 逻辑或
1 =,+=,-, =,*=,/=,%=,&=, ^=, |=, <<=, >>= 赋值、运算且赋值
ly2@DGX:~/sh$ aa=$(( (11 + 3) * 3 / 2 ))    # 注意双括号,与正常加减运算相同
ly2@DGX:~/sh$ echo $aa
21
ly2@DGX:~/sh$ bb=$((14%3))
ly2@DGX:~/sh$ echo $bb
2
ly2@DGX:~/sh$ cc=$((1&&0))
ly2@DGX:~/sh$ echo $cc
0

六、变量测试与内容替换

  • 通过 x 判断 y 是否存在
变量置换方式 变量y没有设置 变量y为空值 变量y设置值
x=${y-新值} x=新值 x为空 x=$y
x=${y:-新值} x=新值 x=新值 x=$y
x=${y+新值} x为空 x=新值 x=新值
x=${y:+新值} x为空 x为空 x=新值
x=${y=新值} x=新值; y=新值 x为空; y值不变 x=$y; y值不变
x=${y:=新值} x=新值; y=新值 x=新值 ;y=新值 x=$y; y值不变
x=${y?新值} 新值输出到标准错误输出(就是 屏幕) x为空 x=$y
x=${y:?新值} 新值输出到标准错误输出 新值输出到标准错误输出 x=$y
ly2@DGX:~/sh$ unset y     # 不管变量 y 是否存在,都先进行清除
ly2@DGX:~/sh$ x=${y-new1}      # 进行测试 
ly2@DGX:~/sh$ echo $x              # 因为变量 y 不存在,所以 x=new1 
new1
ly2@DGX:~/sh$ y=""        # 给变量 y 赋值为空 
ly2@DGX:~/sh$ x=${y-new2}      # 进行测试
ly2@DGX:~/sh$ echo $x              # 因为变量 y 为空,所以 x 也为空

ly2@DGX:~/sh$ y=98        # 给变量 y 赋值
ly2@DGX:~/sh$ x=${y-new2}      # 进行测试
ly2@DGX:~/sh$ echo $x              # 因为变量 y 有值空,所以 x=$y
98
发布了18 篇原创文章 · 获赞 0 · 访问量 1740

猜你喜欢

转载自blog.csdn.net/weixin_44159487/article/details/103172335
今日推荐