Linux:Bash中变量的定义与使用

相关文章

Linux专栏https://blog.csdn.net/weixin_45791458/category_12234591.html


在bash shell中,变量(variable)是参数(parameter)的一类,用于存储值,且变量还可以拥有属性(attributes),这通过bash内建命令declare来完成。

一个存储空字符串的变量被看做是未设置(unset)的变量,可以通过bash内建命令unset将一个已设置的变量转化成未设置的。

给一个变量赋值可以通过下面的命令来完成。

name=[value]

其中的name是一个合法的标识符,由数字、字母和下划线组成,且不能以数字开头。name后面必须紧跟=,不能有空格。如果有空格,则bash会将name解析成一个命令,而后面的=[value]解析为它的参数,这是一个错误。令人遗憾的是,即使用反斜杠\将空格转义,bash依然无法识别name =[value]这样的命令。[value]和=之间可以有空格,但这个空格必须被引号包围或反斜杠转义,否则空格之后的部分会被当做另一个命令名而不是value的一部分(这很有趣,在赋值命令后加其他命令不需要使用;分开,只需要使用空格分开)。value中如果有空格,则也需要使用引号包围或反斜杠转义,原因同理。下面展示了这些性质。

例1
1a=test1   
bash: 1a=test1: command not found...  //错误,name不能以1开头,否则会被识别为命令名

a =test1
bash: a: command not found...         //错误,name和value之间不能有空格,否则name会被单独解析为一个命令名

a\ =test1                             
bash: a =test1: command not found...  //错误,即使转义空格,bash依旧识别不了这种格式

a= test1
bash: test1: command not found...     //错误,这会被解析为将空字符串赋值给a,并执行test1命令

a=\ test1   //bash可以解析这种格式的赋值
echo "$a"   //使用了双引号"",为的是打印出变量a的值中空格,否则其会被解析为分隔符                   
 test1      //前面有空格

a=" test1"  //bash可以解析这种格式的赋值
echo "$a"   //使用了双引号"",为的是打印出变量a的值中空格,否则其会被解析为分隔符                   
 test1      //前面有空格

a=te st1
bash: st: command not found...        //错误,st会被解析为另一个命令

a=test1 echo $a         //这是合法的,echo命令可以正常执行,而无需;分隔
test1

a="te st1"  //bash可以解析这种格式的赋值
echo "$a"   //使用了双引号"",为的是打印出变量a的值中空格,否则其会被解析为分隔符                   
te st1      //变量值中有空格

赋值命令中的value在使用前会首先进行拓展(实际上所有命令在解析前都会进行拓展,比如大括号拓展、波浪号拓展、参数(变量)拓展、命令替换、算数拓展、路径拓展等),在这里我们只涉及到简单的变量拓展,就是以name或{name}这种形式出现的拓展,它们两者的区别在于,后者更清晰的体现了变量名字的范围,而前者依赖bash解析到一个不合法的name字符从而确定name的范围。但需要注意的是,name在拓展后不会被解析为赋值语句,下面举例说明这些性质。

例2
a=test1   //给a变量赋值test1
b=$a      //这条命令在执行前会先拓展为b=test1
echo $b   //这条命令在执行前会先拓展为echo test1
test1
b=$aa     //错误,变量拓展是贪婪的,这代表着bash会把aa解析为一个变量名($aa后的换行符不是合法的命名字符),而不是$a再加上a
b=${a}a   //这是正确的,因为{}明确指出了参数名的范围,所以参数拓展后为b=test1a
echo $b   //这条命令在执行前会先拓展为echo test1a
test1a
c=b      
$c=$a     //错误,即使name也使用了参数拓展,bash也无法识别这种形式的赋值语句
bash: b=test1: command not found...

例1中还使用了双引号"...",它使得其引用内容中的拓展正常进行(它不会使$失去作用,除此之外还有反引号`和某些条件下的转义符\),但它会使得其引用内容中的一些字符失去其特殊意义(空格、换行符等),只代表其字面意思,例如空格符,bash一般会将其当做分隔命令和其选项、参数的依据,而一个包含在双引号""内的空格符则只代表空格的字面意思。而单引号'...'的作用更加激进,它使得其引用内容的拓展也不进行,字符也都失去其特殊意义。

还有一个需要提到的是转义符\,它能使其后的任何一个字符失去其特殊意义(包括自己),当转义符被包括在双引号中,转义符在其后是$、`、"、\或换行符时保持其转义的能力,否则被当做字面量,例如其后紧跟着双引号或单引号的末尾,则双引号或单引号的末尾被转义,则此时后面还需要一个没有被转义的末尾来结束引用,简单来说就是,如果硬碰硬,则引号会被转义符打败。下面的例3说明了这些性质。

例3
echo     hello world   //不使用引号,则其hello world前的空格都会被当做分隔符,最终echo获得两个参数hello和world
hello world
echo "   hello world"  //使用引号,则其hello world前的空格不会被当做分隔符,最终echo获得一个参数"   hello world"
   hello world
a=test1
echo "$a"              //双引号内的拓展可以正常进行,echo命令在执行前被拓展为echo "test1"
test1
echo '$a'              //单引号内的拓展不进行,echo命令为其字面意思echo '$a'
$a
echo "te'$a'st"        //双引号内可以直接嵌套单引号,此时单引号值表现其字面意思,因此$a的拓展可以进行,拓展为echo "te'test1'st"
te'test1'st
echo \$a               //转义符使$失去特殊意义,拓展不进行
$a
echo '$a'              //单引号使$失去特殊意义,拓展不进行
$a
echo "\$a"             //双引号本应使得转义符\失去特殊意义,但其后是$,因此转义符保持其转义能力$被转义,拓展不进行
$a
echo "\1"              //双引号本因转义符\失去特殊意义,只有字面意义
\1
相关推荐
九河云1 小时前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws
Lary_Rock1 小时前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
幺零九零零2 小时前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
云飞云共享云桌面3 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
一坨阿亮4 小时前
Linux 使用中的问题
linux·运维
dsywws5 小时前
Linux学习笔记之vim入门
linux·笔记·学习
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
wclass-zhengge6 小时前
Docker篇(Docker Compose)
运维·docker·容器
李启柱7 小时前
项目开发流程规范文档
运维·软件构建·个人开发·设计规范