变量基础知识

程序由指令加数据所组成,而变量可以理解为数据来源的一种。

变量名可以理解为指向了某个内存空间的地址,对于变量的赋值可理解为向内存空间写入数据,对于变量的引用可理解为从内存空间读取数据。

变量有类型的概念(例如字符串、数字等),不同的类型决定了数据的存储格式、可表示的数据范围以及可参与的运算等。

在编程语言中,可以根据变量的强弱来划分。例如C语言属于强类型变量的语言,该类变量在类型不同的情况下无法直接进行运算。bash脚本则属于弱类型变量的语言,不同类型的变量可以直接运算,默认将所有的变量统一视为字符型,必须在借助第三方工具的情况下才可以进行浮点数的运算,变量无需事先声明即可使用(相当于把声明、赋值和定义数据类型的操作同时实现)。

变量的声明就是事先占用好这个内存空间。变量的强弱之分与是否需要事先声明无关,例如python是强变量类型的编程语言但是其变量不需要事先声明。

变量名可由字母、数字和下划线组成,并且不允许数字打头(几乎所有的编程语言均如此)。变量名要尽量做到见名知意,并且要有一定的规则,根据词语来划分(驼峰法、下划线法等),例如:

my_favorite_sport="basketball"
myFavoriteSport="basketball"

不要使用bash保留字来给变量命名,例如if、else、then等。

变量根据作用域可以划分为三种:

  • 本地变量:仅当前shell有效(即当前bash进程)。
  • 环境变量:当前shell及其子shell(即当前bash进程即其子bash进程)。
  • 局部变量:在某部分代码片段中有效(例如函数)。

除了上述三种,还有位置参数变量和特殊变量:

  • 位置参数变量:用于传参给shell脚本或者函数的变量,例如${1}、${2}等。
  • 特殊变量:在shell中具有特殊含义的变量,例如$?、$-等。

本地变量

本地变量的赋值与引用:

赋值:name=value
引用:${name}或者$name

在我们使用变量的时候,会遇到引号的情况,在bash中,引用(quoting)的作用是抑制bash对某些字符的特殊作用(例如美元符号$,就会做一些变量展开或者特殊符号的处理)。而引号则是引用的其中两种方式(单引号和双引号)。

单引号会使得其中的所有字符只有其字面意义,而双引号只会抑制大部分的特殊字符含义,但是不包括$等其他一些字符。

[root@c7-server ~]# name=zwl
[root@c7-server ~]# echo '${name}'
${name}
[root@c7-server ~]# echo "${name}"
zwl

在引用变量的时候,也建议使用${name},因为这样子才可以支持bash的参数展开功能。

[root@c7-server ~]# echo ${name}
alongdidi
[root@c7-server ~]# echo ${name::}
ong
[root@c7-server ~]# echo $name::
alongdidi::

我们可以通过set(bash内置命令)来查看已经设置的变量名称和值。不过set所显示出来的变量非常多,还包含了环境变量和函数,因此一般需要通过管道传输给less分页或者grep过滤。

~]# set | grep "^name"
name=alongdidi

set还可以用于设置shell的属性(即工作特性)和位置参数,这里不展开。

当某个变量我们不要的时候,可以使用unset来将其取消掉。

[root@c7-server ~]# unset name
[root@c7-server ~]# echo $name [root@c7-server ~]# set | grep "^name"
[root@c7-server ~]#

unset命令可以取消变量,也可以取消函数。

unset [-f] [-v] [name ...]

-f:指明取消的name是函数。

-v:指明取消的name是变量。

这两个选项都可以省略,unset会首先尝试取消一个变量,若失败则再次尝试取消一个函数。某些变量无法被unset,例如只读变量。

可以通过shell内置命令readonly来将shell变量或者函数设置为只读的属性。

readonly [-aAf] [name[=value] ...]
readonly -p

第一种语法,是设置一个变量为只读变量并且可以选择是否赋值,如果此时不赋值,那么设置为只读后就无法再赋值或者改值了。

-a:指明name为索引数组(indexed array)。

-A:指明name为关联数组(associative array)。

-f:指明name为函数(function)。

[root@c7-server ~]# readonly age=
[root@c7-server ~]# age=
-bash: age: readonly variable
[root@c7-server ~]# unset age
-bash: unset: age: cannot unset: readonly variable

-p:单独使用,显示出所有的只读变量和函数。

[root@c7-server ~]# readonly -p
declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -ir EUID=""
declare -ir PPID=""
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID=""
declare -r age=""

注意:declare -r就表示定义一个只读变量,这也是个shell内置命令,后面会提到。

我们刚说了,本地变量的作用域只在当前的shell中,那么在子shell和其他shell中应该是不存在的,我们来证明一下。

[root@c7-server ~]# pstree -ph
sshd(1148)┬─sshd()───bash()
├─sshd(3530)───bash(3536)───pstree(4859)
└─sshd()───bash()
[root@c7-server ~]# name=alongdidi
[root@c7-server ~]# echo $name
alongdidi
[root@c7-server ~]# bash
[root@c7-server ~]# pstree -ph
sshd()─┬─sshd()───bash()
├─sshd()───bash()───bash(4861)───pstree()
└─sshd()───bash()
[root@c7-server ~]# echo $name [root@c7-server ~]#

我们原本在PID为3536的shell(bash进程)中,在当前shell设置了变量name并且可获取其值,随后使用bash命令进入了子shell(PID为4861的bash进程)中再获取这个变量,就获取不到了。

如果我们使用exit命令退回刚才的父shell,就又可以获取到该值。

[root@c7-server ~]# exit
exit
[root@c7-server ~]# echo $name
alongdidi

我们切换使用Xshell再创建了一个新的session,在那个session下尝试获取该变量的值,也是没有的。证明成功。

[root@c7-server ~]# pstree -ph
sshd()─┬─sshd()───bash()
├─sshd()───bash()
└─sshd()───bash(4131)───pstree()
[root@c7-server ~]# echo $name [root@c7-server ~]#

本地变量的生命周期,从创建的时候开始,直到所在的bash进程结束(比如使用exit)或者变量被unset。

环境变量

环境变量的作用域是当前shell及其子shell。因此也可以理解为将变量输出(export)到了子shell中。无论子shell的层数有几层,只要变量具备环境变量的属性,那么它就都会有值。

可以通过export或者declare将变量设置为环境变量。

[root@c7-server ~]# export name
[root@c7-server ~]# bash
[root@c7-server ~]# echo $name
alongdidi
[root@c7-server ~]# bash
[root@c7-server ~]# echo $name
alongdidi
[root@c7-server ~]# bash
[root@c7-server ~]# echo $name
alongdidi

export的语法如下。

export [-fn] [name[=value] ...]
export -p

-f:声明name是一个函数。

-n:去除环境变量的属性。

-p:使用该选项或者仅使用export命令的话,可以查看当前所有的环境变量。declare -x有同效。外部命令env和printenv也可以实现。

export是专门用于设置与环境变量属性相关的命令。declare是设置所有与变量相关的属性(只读、环境变量、整型、索引数组、关联数组)等等。

多命令执行

;:分号,命令按顺序执行,执行完第一个再执行第二个,后一个命令的执行与否与前一个命令的执行成功与否无关。

~]# COMMAND1; COMMAND2

&&:逻辑与,只有当COMMAND1执行成功的时候,才执行COMMAND2。类似于逻辑与运算,a && b,当a为1的时候(执行成功)还需要看b的值(即还需要执行b)才能决定整个表达式的值,如果a为0了,那么整个表达式必然为0,就不需要看b的值了(b就可以不执行),这也叫短路法则。

~]# COMMAND1 && COMMAND2

||:逻辑或,只有当COMMAND1执行失败的时候,才执行COMMAND2。

~]# COMMAND1 || COMMAND2

Bash脚本编程之变量与多命令执行的更多相关文章

  1. 5-2 bash 脚本编程之一 变量、变量类型等

    1. bash变量类型 1. 环境变量 2. 本地变量(局部变量) 3. 位置变量 4. 特殊变量 2. 本地变量 VARNAME=VALUE, 整个bash进程 3. 环境变量 作用域为当前shel ...

  2. bash脚本编程之一 变量、变量类型等

    变量的内容 1.变量命名:            1.只能包含字母.数字和下划线,并且不能以数字开头,    2.不应该跟系统中已有的环境变量重名    3.最好能见名知意 2.变量赋值: 设置变量: ...

  3. 《鸟哥的Linux私房菜》学习笔记(8)——bash脚本编程之变量

    一.变量命名                                                             1.只能包含字母.数字和下划线,并且不能以数字开头,    2.不 ...

  4. 脚本命令高级Bash脚本编程指南(31):数学计算命令

    题记:写这篇博客要主是加深自己对脚本命令的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 高等Bash脚本编程指南(31):数学盘算命令 成于坚持,败于止步 操作数字 factor ...

  5. 高级Bash脚本编程指南(27):文本处理命令(三)

    高级Bash脚本编程指南(27):文本处理命令(三) 成于坚持,败于止步 处理文本和文本文件的命令 tr 字符转换过滤器. 必须使用引用或中括号, 这样做才是合理的. 引用可以阻止shell重新解释出 ...

  6. Bash脚本编程学习笔记04:测试命令test、状态返回值、位置参数和特殊变量

    我自己接触Linux主要是大学学习的Turbolinux --> 根据<鸟哥的Linux私房菜:基础篇>(第三版) --> 马哥的就业班课程.给我的感觉是这些课程对于bash的 ...

  7. 高级bash脚本编程(三)

    高级bash脚本编程 知识点 compound 和 comparison -a 逻辑与 exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话,那么结果为真. -o 逻辑或 exp1 ...

  8. 高级Bash脚本编程(二)

    高级Bash脚本编程(二) 退出 退出状态码 退出:exit 被用来结束一个脚本,它也返回一个值,并且这个值会传递给脚本的父进程,父进程会使用这个值做下一步的处理. 每个命令都会返回一个退出状态码,成 ...

  9. 高级Bash脚本编程(一)

    高级Bash脚本编程 Bash 它是能力很强的计算机语言,被称为解释性语言或脚本语言,它可以调用所有的UNIX命令和工具再加上公共程序. Bash中的特殊字符 注释(#) (除#!外,#!是用于指定当 ...

随机推荐

  1. ctf线下赛中检测外来IP的shell脚本

    该脚本可用于ctf线下赛中,用来检测攻击IP的接入,及时做出响应. #!/bin/bash #写自己队的ip ipA="172.22.60.230" ipB="172.2 ...

  2. 全球 43 亿 IPv4 地址已耗尽!IPv6,刻不容缓

    大家都知道目前网络协议使用的主要是 IPv4,全称为 Internet Protocol version 4,作用是为每一个网络和每一台主机分配一个 IP,IP 地址是一个 32 位的二进制数,算下来 ...

  3. C#取视频某一帧图片

    首先下载 ffmpeg http://ffmpeg.org/ 注意一定要从官网下载,其他地方可以会有问题 解压后在 bin 目录下找到 ffmpeg.exe 用到的使命是 -i 视频地址 -ss 第几 ...

  4. 王院生:Apache APISIX 微服务网关极致性能架构解析

    2019 年 10 月 27 日,又拍云联合 Apache APISIX 社区举办 API 网关与高性能服务最佳实践丨Open Talk 杭州站活动,Apache APISIX PPMC 成员王院生做 ...

  5. 设置颜色的函数:rgb,hsv,color palettes

    1.grb函数 (1)功能: 通过对给定的三个基本色红,绿,蓝的颜色饱和度(intensity)的设定,而创造颜色. 阿尔法透明度(alpha transparent):其值也能被指定,从0到max ...

  6. NFS介绍、服务端安装配置、NFS配置选项

    6月21日任务 14.1 NFS介绍14.2 NFS服务端安装配置14.3 NFS配置选项 14.1 NFS介绍 14.2 NFS服务端安装配置 1.首先需要2台机器,一台是服务端,一台是客户端,分别 ...

  7. javaWeb学习总结——文件上传、下载

    目录 1.文件上传环境搭建 2.文件上传代码实现 3.关于下载 @ 嘿,熊dei,你不得不知道在Web开发中,文件上传和下载功能是非常常用的功能,关于文件上传,浏览器上传[文件以流的形式传输]--&g ...

  8. Python微信公众号教程基础篇——收发文本消息

    1. 概述: 在本篇教程中,你将学会使用华为云弹性云服务器(以下简称 ECS)搭建微信公众号处理后台,使用Python语言编写对应的微信消息处理逻辑代码,接收从微信服务端转发过来的消息,并返回处理结果 ...

  9. 转:Java transient关键字使用小记

    哎,虽然自己最熟的是Java,但很多Java基础知识都不知道,比如transient关键字以前都没用到过,所以不知道它的作用是什么,今天做笔试题时发现有一题是关于这个的,于是花个时间整理下transi ...

  10. MRC ARC 混编

    今天一个人问我 什么是MRC 什么是ARC 要是一个工程里用到了MRC和ARC 怎么办 我当时就无语了 什么情况 这是....   好了正经一点 我说一下iOS5.0以后就开始可以使用ARC( Aut ...