shell编程之变量

一、变量

1.变量的命名

shell中的变量必须以字母或者下划线开头,后面可以跟数字、字母和下划线,变量长度没有限制。

#正确的变量命名

firstname

FIRSTNAME

_helloworld

Fullname

big_data

Fullname

Person01

#错误的变量命名

51paly #变量不能以数字开头

*badname #变量不能以特殊字符开头

PS1 #变量不能以特殊字符开头

for #变量不能使用shell关键字

按照以上的变量命名规则定义变量abc,从理论上来说是可行的,但是一个好的习惯是变量最好能表明它代表的含义。比如说Student_ID,一看就知道它所表达的是“学号"的意思,绝对比number这种模棱两可的变量要清晰得多名,不仅看代码的人觉得简单明了,而且有利于后期的代码维护。更好地习惯则是加上一些注释,但是也不要太过拘泥,如下所示:

#定义学号   #使用注释解释变量使后期阅读更为清晰

Student_ID

#定义日期 #这种注释就显得有所拘泥

DATE

2.变量的赋值和取值

#定义变量:变量名=变量值

#注意点一:变量名和变量值之间用等号紧紧相连,之间没有任何空格

[root@Cfhost-170820-UCNK ~]# name=john
[root@Cfhost-170820-UCNK ~]# name = john
-bash: name: command not found
[root@Cfhost-170820-UCNK ~]# name="john"

#注意点二:当变量中有空格时必须用引号括起,否则会出现错误

#其中的引号可以是双引号,也可以是单引号

[root@Cfhost-170820-UCNK ~]# name="john wang"
[root@Cfhost-170820-UCNK ~]# name=john wang
-bash: wang: command not found

变量取值很简单,只需要在变量名前加上$符号即可,严谨一点的写法是${},如下所示:

[root@Cfhost-170820-UCNK ~]# echo $name
john wang
[root@Cfhost-170820-UCNK ~]# echo ${name}
john wang

#使用${}获取变量值是一种相对比较保险的方式

[root@Cfhost-170820-UCNK ~]# name=john
[root@Cfhost-170820-UCNK ~]# name1="$name"
[root@Cfhost-170820-UCNK ~]# echo $name1
john
[root@Cfhost-170820-UCNK ~]# name1='$name'
[root@Cfhost-170820-UCNK ~]# echo name1
name1

由于Shell具有“弱变量"的特性,因此即便在没有预先声明变量的时候也可以引用的,而且没有任何报错或提醒,这可能会造成脚本中引用不正确的变量,从而导致脚本异常,但是却很难找出原因。在这种情况下,可以设置脚本运行时必须遵循“先声明再使用"的原则,这样一旦脚本中出现使用未声明的变量的情况则立刻报错。

[root@Cfhost-170820-UCNK ~]# echo $unDefinedVar

#因为该变量未声明,所以值为空,但没有任何报错

#设置变量必须先声明再使用

[root@Cfhost-170820-UCNK ~]# shopt -s -o nounset
[root@Cfhost-170820-UCNK ~]# echo $unDefinedVar
-bash: unDefinedVar: unbound variable

3.取消变量

[root@Cfhost-170820-UCNK ~]# name=john
[root@Cfhost-170820-UCNK ~]# echo $name
john #此时变量有值

[root@Cfhost-170820-UCNK ~]# unset name
[root@Cfhost-170820-UCNK ~]# echo $name
-bash: name: unbound variable

#报错为没有绑定变量

#取消函数

unset_function(){
echo "Hello,World"

}

unset unset_function

unset_function #由于函数已经被取消,这里调用会出错

 

4.特殊变量

Shell中还有一些预先定义的特殊只读变量,它们的值只有在脚本运行时才能确定。首先是”位置参数“,位置参数的命名简单直接,比如,脚本本身为$0,第一个参数为$1,第二个参数为$2,第三个参数为$3,以此类推。当位置参数的个数大于9时,需要用${}括起来标识,比如说第10个位置参数应该记为${10}。另外,$#表示脚本参数的个数总和,$@或$*表示脚本的所有参数。请看下面示例:

[root@Cfhost-170820-UCNK ~]# cat posion.sh
#!/bin/bash
echo "This script is name is: $0"
echo "$# Parameters in total"
echo "All parameters list as: $@"
echo "The first parameter is $1"
echo "The second parameter is $2"
echo "The third parameter is $3"
[root@Cfhost-170820-UCNK ~]# bash posion.sh a b c
This script is name is: posion.sh
3 Parameters in total
All parameters list as: a b c
The first parameter is a
The second parameter is b
The third parameter is c

脚本或命令返回值:$?

在管理员登录到系统中交互式地输入命令时,系统也会及时在屏幕上输出内容给予反馈。比如说本想使用ifconfig查看网卡状态,但是将命令错写成ifconfi,系统会立刻给出command not found 的提示,这种提示确实能让管理员感觉到系统非常友好。

[root@Cfhost-170820-UCNK ~]# ifconfi
-bash: ifconfi: command not found

 

但是在很多后台脚本是需要每天自动运行的,比如说每天凌晨两点的数据库备份。在这种情况下一旦出错是不可能在第一时间知道的。那靠什么判断出错呢?

再考虑一个场景:有些自动备份脚本在按时完成本地数据备份后,还会复制一份放到远程主机上(通过scp就可以做到)。不过在复制前需要先确认远程主机是否还”活着",这可以通过ping远程主机做到。如果能ping通则进行复制,如果ping不通则采取其他动作。这里又如何判断是否ping成功了呢?

这时就需要借助命令的返回值来判断了。Linux中规定正常退出的命令和脚本应该以0作为返回值,任何非0的返回值都表示命令未正确退出或未正常执行。

在第一个例子中,输错命令后立即查看当时特殊变量$?的值为127;第二个例子中,ping不通某个地址时查看当时的$?值为1.注意,$?永远是上一个命令的返回值,所以要查看某个

命令的返回值必须在运行该命令后立即查看$?。在自动化脚本中,也可以通过$?变量的值判断之前命令的执行状态,从而采取不同的动作。

#输入错误的命令时的返回值

[root@Cfhost-170820-UCNK ~]# ifconfi
-bash: ifconfi: command not found
[root@Cfhost-170820-UCNK ~]# echo $?
127

 #尝试ping主机ping不通时的返回值

[root@Cfhost-170820-UCNK ~]# ping 192.168.160.66 -c 1
PING 192.168.160.66 (192.168.160.66) 56(84) bytes of data.

--- 192.168.160.66 ping statistics ---
1 packets transmitted,0 received,100% packet loss,time 10000ms

[root@Cfhost-170820-UCNK ~]# ^C
[root@Cfhost-170820-UCNK ~]# echo $?
130

5.数组

数组是一种特殊的数据结构,其中每一项被称为一个元素,对于每个元素,都可以用索引方式取出元素的值。使用数组的典型场景是一次性要记录很多类型相同的数据时(但不是说一定要相同,因为Shell变量是弱类型的,并不要求数组的每个元素都是相同类型)。比如,为了记录班级中所有人的计算机成绩,如果不用数组来处理就只能定义所有人成绩的变量,这就会显得非常繁琐。Shell中的数组对元素个数没有限制,但是只支持一维数组,这一点和许多语言不同。

a.数组的定义

数组的定义方法如下:用declare命令定义数组Array,并将第一个元素赋值为0,第二个元素赋值为1,其下标(也就是索引)则分别是0和1(记住数组的索引从0开始计数的),然后打印出第一个元素的值

#定义名为Array的索引数组

[root@Cfhost-170820-UCNK ~]# declare -a Array

#数组的下标从0开始计数,定义了第一个元素值为0,第二个元素值为1

[root@Cfhost-170820-UCNK ~]# Array[0]=0
[root@Cfhost-170820-UCNK ~]# Array[1]=1

如果说数组Array的前两个元素“类型相同"(严格意义上这么说是不对的),那么第三个元素就显得”另类"了:赋值为一个字符串。这又一次验证了Shell变量是弱类型的,这在很多语言中是不可能的。

[root@Cfhost-170820-UCNK ~]# Array[2]="HelloWorld"

和其他变量一样,Shell对于数组变量的声明也非常宽松,而且随时都可以根据需要增加变量中的元素。相比其他语言,Shell的数据更为灵活。在很多语言中,一旦对数组进行初始化就不能改变其大小了。

[root@Cfhost-170820-UCNK ~]# declare -a Array
[root@Cfhost-170820-UCNK ~]# Array[0]=0
[root@Cfhost-170820-UCNK ~]# Array[1]=1
[root@Cfhost-170820-UCNK ~]# Array[2]"HelloWorld"
-bash: Array[2]HelloWorld: command not found
[root@Cfhost-170820-UCNK ~]# Array[2]="HelloWorld"
[root@Cfhost-170820-UCNK ~]# declare -a Name=('john','sue')
[root@Cfhost-170820-UCNK ~]# Name[2]='wang'
[root@Cfhost-170820-UCNK ~]# Name=('john' 'sue')
[root@Cfhost-170820-UCNK ~]# Score=([3]=3 [5]=5 [7]=7)

#数组在创建的时候同时赋值

[root@Cfhost-170820-UCNK ~]# declare -a Name=('john' 'sue')

#增加元素

[root@Cfhost-170820-UCNK ~]# Name[2]='wang'

#更简单的创建数组的方式--不使用declare关键字

[root@Cfhost-170820-UCNK ~]# Name=('john' 'sue')

还可以给特定的元素赋值。下面的实例就是只对第四个、第六个、第八个元素进行赋值

#跳号赋值

[root@Cfhost-170820-UCNK ~]# Score=([3]=3 [5]=5 [7]=7)

#数组取值:知道了如何定义数组和赋值元素后,下面就要了解数组一些常见操作。最简单的操作就是数组取值,其格式为:${数组名[索引]}.比之前定义的数组Array、Name为例,取值演示如下·:

[root@Cfhost-170820-UCNK ~]# echo ${Array[0]}
0
[root@Cfhost-170820-UCNK ~]# echo ${Array[2]}
HelloWorld
[root@Cfhost-170820-UCNK ~]# echo ${Name[0]}
john
[root@Cfhost-170820-UCNK ~]# echo

[root@Cfhost-170820-UCNK ~]# echo ${Name[1]}
sue

#指定索引,只能取单个值,要是想一次性取出所有元素的值,可以采取以下两种方式:
[root@Cfhost-170820-UCNK ~]# echo ${Array[@]}
0 1 HelloWorld
[root@Cfhost-170820-UCNK ~]# echo ${Array[*]}
0 1 HelloWorld

从表面上看两者没有什么区别,但是${Array[@]}得到的是以空格隔开的元素值,而${Array[*]}的输出是整个字符串。

数组长度:即数组个数。利用"@"或"*“字符,可以将数组扩展成列表,然后使用"#"来获取数组元素的个数,如下所示:

[root@Cfhost-170820-UCNK ~]# echo ${#Array[@]}
3
[root@Cfhost-170820-UCNK ~]# echo ${#Array[*]}
3

如果某个元素是字符串,还可以通过指定索引的方式获得该元素长度,如下所示:

[root@Cfhost-170820-UCNK ~]# echo ${#Array[2]}
10

 数组截取:可以截取某个元素的一部分,对象可以是整个数组或某个元素。

#取出数组的第一、第二个元素

[root@Cfhost-170820-UCNK ~]# echo ${Array[@]:1:2}
1 HelloWorld

#取出第二个元素从第0个字符开始连续5个字符
[root@Cfhost-170820-UCNK ~]# echo ${Array[2]:0:5}
Hello

#l连接数组:将n个数组进行拼接操作

[root@Cfhost-170820-UCNK ~]# Conn=($Array[@] ${Name[@]})
[root@Cfhost-170820-UCNK ~]# echo ${Conn[@]}
0[@] john sue

 

 

#取消数组或元素:和取消一般变量一样,取消一个数组的方式也可以使用unset命令

#取消数组中的一个元素
[root@Cfhost-170820-UCNK ~]# unset Array[1]

#取消整个数组

[root@Cfhost-170820-UCNK ~]# echo ${Array[@]}
0 HelloWorld
[root@Cfhost-170820-UCNK ~]# unset Array
[root@Cfhost-170820-UCNK ~]# echo

[root@Cfhost-170820-UCNK ~]# 4{Array[@]}
-bash: 4{Array[@]}: command not found
[root@Cfhost-170820-UCNK ~]# echo ${Array[@]}

 6.只读变量

只读变量又称常量,是通过readonly内建命令创建的变量。这种变量在声明时就·要求赋值,并且之后无法修改,这和之前讲的使用declare -r 声明只读变量的效果是一致的。

[root@Cfhost-170820-UCNK ~]# readonly RO=100
[root@Cfhost-170820-UCNK ~]# RO=200
-bash: RO: readonly variable

 

7.变量的作用域

变量的作用域又叫命名空间,表示变量的上下文。相同的变量可以在多个命名空间中定义,并且彼此之间互不干涉,所以在一个新的命名空间中可以自定义任何变量,因为所定义的变量都只在各自命名空间中。

在Linux系统中,不同进程ID的shell默认为一个不同的命名空间。

Shell变量的作用域是在本Shell内,属于本Shell的全局变量,也就是从定义该变量的地方开始到结束,或到主动使用unset删除该变量的地方为止。在变量的作用域内,该变量是可见的,在函数内对变量也是可以访问的、可修改的,这和C语言不同。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Centos系统之Shell编程基础知识
从Export理解Shell环境和变量生存期
linux shell数组变量、类型及规则
Centos编程Shell基本工作原理方案
Centos操作系统编程之Shell 问答录
rsync-linux备份脚本
Linux Shell编程入门 1-4
用shc加密shell脚本
centos每天自动备份mysql数据库
shell字符串处理
awk 用法:awk ' pattern {action} ' 变量名 含义 ARGC 命令行变元个数 ARGV 命令行变元数组 FI
sed之仅打印相邻重复的行 cat file aaa bbb bbb ccc ddd eee eee fff 只显示重复的行: bbb bbb eee eee sed -n ':a;N;/\(
压缩: tar -zcvf 压缩后文件名.tar.gz 被压缩文件 解压: tar -zxvf 被解压文件 注意:不要有多余的空格,一个空格即可。 具体的可以在linux环境下 用 tar --hel
sed命令行格式为: sed [-nefri] ‘command’ 输入文本/文件 常用选项: -n∶取消默认的输出,使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料
#假设文件名是:fortest.gtfdeclare -i fileLinesfileLines=`sed -n '$=' fortest.gtf`echo $fileLines#--
获得每行的最后一个逗号后边的内容.例如:KIAA1967 KIAA1967, xxxxSECIS biding proin 2-like, SECISBP2L, yyyy 1234ankyrin re
bash 正则表达式匹配,一行文本中 “包含 ABC” 并且 “不包含 XYZ”A文件: XXXX ABC XXX4444444444444444XXXX ABC XXX XYZ66666666666
shell/bash 让vi/vim显示空格,及tab字符Vim 可以用高亮显示空格和TAB。文件中有 TAB 键的时候,你是看不见的。要把它显示出来::set listTAB 键显示为 ^I, $显
输出到文件log中,并在屏幕上显示:#ls >&1 | tee log追加输出到文件log中,并在屏幕上显示:#ls >&1 | tee -a log
Suppose we have a file contains the following information, termed input_file:A 0B 1C 21.Read file on