变量就是程序设计语言中的一个可以变化的量,当然,可以变化的是变量的值。几乎所有的程序设计语言中都有定义变量,并且其涵义也大同小异。从本质上讲,变量就是在程序中保存用户数据的一块内存空间,而变量名就是这块内存空间的地址。
在程序的执行过程中,保存数据的内存空间的内容可能会不断地发生变化,但是,代表内存地址的变量名却保持不变。
在Shell中,变量名可以由字母、数字或者下划线组成,并且只能以字母或者下划线开头。对于变量名的长度,Shell并没有做出明确的规定。因此,用户可以使用任意长度的字符串来作为变量名。但是,为了提高程序的可读性,建议用户使用相对较短的字符串作为变量名。
在一个设计良好的程序中,变量的命名有着非常大的学问。通常情况下,用户应该尽可能选择有明确意义的英文单词作为变量名,尽量避免使用拼音或者毫无意义的字符串作为变量名。这样的话,用户通过变量名就可以了解该变量的作用。
Shell是一种动态类型语言和弱类型语言,即在Shell中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。准确地讲,Shell中的变量是不分数据类型的,统一地按照字符串存储。但是根据变量的上下文环境,允许程序执行一些不同的操作,例如字符串的比较和整数的加减等等。
强类型和弱类型主要是站在变量类型处理的角度进行分类的。强类型是指不允许隐式变量类型转换,弱类型则允许隐式类型转换。
可以使用declare定义变量的类型:declare attribute variable
注:declare命令还可输出所有的变量、函数、整数和已经导出的变量
分为环境变量(全局变量)和普通变量(局部变量)
1> 环境变量也可称为全局变量,可以在创建它们的shell及其派生出来的任意子进程shell中使用(su -切换用户会读取新的环境变量),环境变量又可分为自定义环境变量和bash内置的环境变量。
自定义环境变量
指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。即该环境变量只在当前shell和子shell中有效。如果希望永久保存环境变量,可以在配置文件中设置。
注意:按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前, 都应该用命令export导出。
2> 普通变量
与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,例如函数内部。在Shell语言中,可以在函数内部通过local关键字定义局部变量,另外,函数的参
数也是局部变量
举例:全局变量和局部变量的区别
[root@centos-7 day2]# vim 6.sh
#########################
#File name:6.sh
#Version:v1.0
#Email:[email protected]
#Created time:2021-08-14 18:37:36
#Description:
#########################
#定义函数
func()
{
#输出全局变量v1的值
echo "global variable v1 is $v1"
#定义局部变量v1
local v1=2
#输出局部变量v1的值
echo "local variable v1 is $v1"
}
#定义全局变量v1
v1=1
#调用函数
func
#输出全局变量v1的值
echo "global variable v1 is $v1"
[root@centos-7 day2]# chmod a+rx 6.sh
[root@centos-7 day2]# ./6.sh
global variable v1 is 1
local variable v1 is 2
global variable v1 is 1
在Shell中,通常情况下用户可以直接使用变量,而毋需先进行定义,当用户第一次使用某个变量名时,实际上就同时定义了这个变量,在变量的作用域内,用户都可以使用该变量。
1.变量定义示例:变量名=变量值
#!/bin/bash
#定义变量a
a=1
#定义变量b
b="hello"
#定义变量c
c="hello world"
#定义备份路径
bak_dir=/data/backup
#把一个命令的结果赋值变量
变量名=`ls`
变量名=$(ls)
1> "="前后不能有空格
[root@centos-7 day2]# a= 3
-bash: 3: 未找到命令
[root@centos-7 day2]# b =4
-bash: b: 未找到命令
2>字符串类型建议用引号括起来,尤其是特殊字符或有空格
stu_name="zhang san"
引用变量:$变量名 或者 ${变量名}
查看变量:echo $变量名,set(可查看所有变量:包括自定义变量和环境变量),env显示全局变量,declare输出所有的变量、函数、整数和已经导出的变量。
取消变量:unset 变量名
作用范围:仅在当前shell中有效。
注:可使用export指令将变量转换成环境变量
2、位置参数和预定义变量
许多情况下,Shell脚本都需要接收用户的输入,根据用户输入的参数来执行不同的操作。
从命令行传递给Shell脚本的参数又称为位置参数,Shell脚本会根据参数的位置使用不同的位置参数变量读取它们的值。
变量 | 说明 |
---|---|
$# | 命令行参数的个数 |
$n | 表示传递给脚本的第n个参数,例如$1表示第一个参数,$2表示第二个参数,$3表示第三个参数 |
$0 | 当前脚本的名称 |
$* | 以"参数1 参数2 参数3…"的形式返回所有参数的值 |
$@ | 以“参数1”“参数2”“参数3”…的形式返回所有的值 |
$? | 前一个命令或者函数的返回状态码。 ? 的 返 回 值 用 法 : ( 1 ) 判 断 命 令 、 脚 本 或 函 数 等 程 序 是 否 执 行 成 功 ( 2 ) 若 在 脚 本 中 调 用 执 行 “ e x i t 数 字 ” , 则 会 返 回 这 个 数 字 给 “ ?的返回值用法:(1)判断命令、脚本或函数等程序是否执行成功(2)若在脚本中调用执行“exit 数字”,则会返回这个数字给“ ?的返回值用法:(1)判断命令、脚本或函数等程序是否执行成功(2)若在脚本中调用执行“exit数字”,则会返回这个数字给“?”变量(3)如果是在函数里,则通过“return 数字”把这个数字以函数值的形式传给“$?” |
$$ | 返回本程序的进程ID(PID),不常用 |
$! | 获取上一个在后台工作的进程的进程号,不常用 |
$_ | 保存之前执行的命令的最后一个参数,不常用 |
举例:
[root@centos-7 day2]# vim param.sh
#!/bin/bash
echo "第1个位置参数是$1"
echo "第2个位置参数是$2"
echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID是: $$"
[root@centos-7 day2]# bash param.sh shuju1 shuju2
第1个位置参数是shuju1
第2个位置参数是shuju2
所有参数是: shuju1 shuju2
所有参数是: shuju1 shuju2
参数的个数是: 2
当前进程的PID是: 1542
$? 举例:
[root@centos-7 day2]# vim ping.sh
ping -c2 $1 &> /dev/null
if [ $? = 0 ];then
echo "host $1 is ok"
else
echo "host $1 is fail"
fi
[root@centos-7 day2]# chmod a+rx ping.sh
[root@centos-7 day2]# ./ping.sh 192.168.233.128
host 192.168.233.128 is ok
$* 和 $@举例:
[root@centos-7 day2]# set -- "i have" a cat #利用set命令设置位置参数
[root@centos-7 day2]# echo $#
3
[root@centos-7 day2]# echo $*
i have a cat
[root@centos-7 day2]# echo $@
i have a cat
[root@centos-7 day2]# for i in $*;do echo $i;done
i
have
a
cat
[root@centos-7 day2]# for i in "$@";do echo $i;done
i have
a
cat
[root@centos-7 day2]# shift #使用该指令可将位置参数左移一位
[root@centos-7 day2]# echo $1
a
[root@centos-7 day2]# shift
[root@centos-7 day2]# echo $1
cat
在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通字符来处理。
符号 | 说明 |
---|---|
转义字符“\” | 如果将\放到特殊字符前面,shell就忽略这些特殊字符的原有含义,把它们当作普通字符对待 |
单引号 | 如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义被忽略 |
双引号 | 双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍然有一些特殊字符保留自己的特殊含义,比如”$“和“\”以及“ ` ” |
说明:反引号中的字符串将被解释为shell命令
[root@centos-7 day2]# echo "current_user is: $USER"
current_user is: root
[root@centos-7 day2]# echo 'current_user is: $USER'
current_user is: $USER
[root@centos-7 day2]# echo "current_user is: `whoami`"
current_user is: root
[root@centos-7 day2]# echo 'current_user is: `whoami`'
current_user is: `whoami`
运算符 | 说明 |
---|---|
+、- | 求和、差 |
*、/、% | 求乘积,商,余数 |
** | 幂运算,例如3**3是求3的立方,即27 |
+=、-=、*=、/=、%= | 例a+=1相当于a=a+1 |
++variable、–variable | 先将变量variable的值加1,然后再赋给variable; 先将变量variable的值减1,然后再赋给variable |
variable++、variable– | 先使用variable的值,然后再将该变量的值加1; 先使用variable的值,然后再将该变量的值减1 |
位运算符<<、>> | 位运算通常出现在整数间,它针对的不是整个整数,而是其二进制表示形式中的某个或者某些位(bit)。例如,2>>1是将二进制形式的2,即10,左移1位,从而变成100,即4。 左移,4<<2,将4左移2位,结果为16; 右移,8>>2,将8右移两位,结果为2 |
<<=、>>= | 将变量的值左移指定位数之后重新赋给该变量,x<<=3,将x的值左移3位,重新赋给变量x; 将变量的值右移指定位数之后重新赋给该变量,x>>=4,将变量x的值右移4位后重新赋给变量x。 |
运算操作符与运算命令 | 意义 | 说明 |
---|---|---|
(()) | 用于整数运算的常用运算符 | 在(())中使用变量时可以去掉变量前$符号 |
let | 用于整数运算 | 使用let命令可以执行一个或者多个算术表达式,其中的变量名毋需使用$符号 |
expr | 可用于整数运算,但还有很多其他的额外功能 | 使用expr时,运算符及用于计算的数字左右都至少有一个空格,否则会报错;使用乘号时,必须使用反斜线屏蔽其特定含义;使用expr做计算,将一个未知的变量和一个已知的整数相加,看返回码是否为0,如果为0就认为做加法的变量为整数,否则就不是整数。 |
bc | linux下的一个计算器程序(适合整数及小数运算) | [root@localhost test4]# echo seq -s “+” 10 = seq -s “+” 10 |
$[] | 用于整数运算 | |
awk | awk既可以用于整数运算,也可以用于小数运算 | |
declare | 定义变量值和属性,-i参数可以用于定义整形变量,做运算 |
举例:
[root@centos-7 day2]# r=$((2+5*8))
[root@centos-7 day2]# echo $r
42
[root@centos-7 day2]# let r=3+2
[root@centos-7 day2]# echo $r
5
[root@centos-7 day2]# r=`expr 4+2`
[root@centos-7 day2]# echo $r
4+2
[root@centos-7 day2]# r=`expr 4 + 2`
[root@centos-7 day2]# echo $r
6
#使用expr计算字符的长度
[root@centos-7 day2]# char="i have a"
[root@centos-7 day2]# expr length "$char"
8
[root@centos-7 day2]# r=$[3+2]
[root@centos-7 day2]# echo $r
5
[root@centos-7 day2]# awk 'BEGIN {print 2+3*2}'
8
[root@centos-7 day2]# echo "6.282 3.14" | awk '{print ($1-$2)}'
3.142
[root@centos-7 day2]# declare -i r=3+2
[root@centos-7 day2]# echo $r
5
实验:计算用户输入的任意两个整数的和、差、乘积、商、余数。
方法一:
[root@centos-7 day2]# vim f1.sh
#!/bin/bash
a=$1
b=$2
echo a+b=$(($a+$b))
echo a-b=$((a-b))
echo a*b=$((a*b))
echo a/b=$((a/b))
echo a%b=$((a%b))
[root@centos-7 day2]# chmod a+rx f1.sh
[root@centos-7 day2]# ./f1.sh 10 3
a+b=13
a-b=7
a*b=30
a/b=3
a%b=1
方法二:
[root@centos-7 day2]# vim f2.sh
read -p "please input two number:" a b
echo $a+$b=$(($a+$b))
echo $a-$b=$((a-b))
echo $a*$b=$((a*b))
echo $a/$b=$((a/b))
echo $a%$b=$((a%b))
[root@centos-7 day2]# chmod a+rx f2.sh
[root@centos-7 day2]# ./f2.sh
please input two number:3 4
3+4=7
3-4=-1
3*4=12
3/4=0
3%4=3
表达式 | 说明 |
---|---|
${parameter} | 返回变量的内容 |
${#parameter} | 返回变量内容的长度(按字符) |
${paramater:offset} | 在变量${parameter}中,从位置offset之后开始提取子串到结尾 |
${paramater:offset:length} | 在变量${parameter}中,从位置offset之后开始提取长度为length的子串 |
${parameter#word} | 从变量${parameter}开头开始删除最短匹配的word子串 |
${parameter##word} | 从变量${parameter}开头开始删除最长匹配的word子串 |
${parameter%word} | 从变量${parameter}结尾开始删除最短匹配的word子串 |
${parameter%%word} | 从变量${parameter}结尾开始删除最长匹配的word子串 |
${parameter/pattern/string} | 使用string代替第一个匹配的pattern |
${parameter//pattern/string} | 使用string代替所有匹配的pattern |
举例:截取字符串
[root@centos-7 day2]# str1="hello world" #返回变量长度
[root@centos-7 day2]# echo ${#str1}
11
#变量截取
#指定起始位置,一直到结束
[root@centos-7 day2]# echo ${str1:1}
ello world
#指定长度,不指定起始位置默认从开头开始
[root@centos-7 day2]# echo ${str1::3}
hel
#指定起始位置和长度
[root@centos-7 day2]# echo ${str1:1:3}
ell
#从右边第几个字符开始,及字符的个数
[root@centos-7 day2]# echo ${str1:0-1:1}
d
#输出右边的几个字符
[root@centos-7 day2]# echo ${str1:0-5}
world
[root@centos-7 day2]# echo ${str1: -5}
world
#提取完整字符串
[root@centos-7 day2]# echo ${str1:-5}
hello world
举例:删除字符串
#获取后缀名tar.gz
[root@centos-7 day2]# filename=testfile.tar.gz
[root@centos-7 day2]# file=${filename#*.}
[root@centos-7 day2]# echo $file
tar.gz
#获取后缀名.gz
[root@centos-7 day2]# filename=testfile.tar.gz
[root@centos-7 day2]# file=${filename##*.}
[root@centos-7 day2]# echo $file
gz
#截取testfile.tar
[root@centos-7 day2]# filename=testfile.tar.gz
[root@centos-7 day2]# file=${filename%.*}
[root@centos-7 day2]# echo $file
testfile.tar
#截取testfile
[root@centos-7 day2]# filename=testfile.tar.gz
[root@centos-7 day2]# file=${filename%%.*}
[root@centos-7 day2]# echo $file
testfile