变量
一 变量
变量是暂时存储数据的地方及数据标记,所存储的数据存在于内存空间中,通过正确地调用内存空间中的变量的名字就可以取出与变量对应的数据。
定义变量的规范:
1.变量名称可以由字母、数字和下划线组成,但是不能以数字开头,变量中间不能有空格 2.在Bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必修指定变量类型为数值型 3.变量用等号连接值,等号左右两侧不能有空格 4.变量的值如果有空格,需要使用单引号或双引号包括。如:“test="hello world!"”。其中双引号括起来的内容“$”、“\”和反引号都拥有特殊含义,而单引号括起来的内容都是普通字符 5. 将所有 字符串 用双引号括起来使用,会减少编程遇到怪异的错误。使用: "$变量名" 或用 "${变量名}"
变量分类:
可分为两类:环境变量(全局变量) 和 普通变量(局部变量)
环境变量也可称为全局变量,可以在创建它们的shell及其派生出来的任意子进程shell中使用。环境变量有可分为 自定义环境变量
和bash内置的环境变量。
不同变量也可称为局部变量,只能在创建它们的Shell函数或Shell脚本中使用。普通变量一般由开发者在开发脚本程序时创建。
[root@localhost ~]# a=192.168.1.2 [root@localhost ~]# b='192.168.1.2' [root@localhost ~]# c="192.168.1.2" [root@localhost ~]# echo "a=$a" [root@localhost ~]# echo "b=$b" [root@localhost ~]# echo "c=${c}" 此时a,b,c: a=192.168.1.2 b=192.168.1.2 c=192.168.1.2 ===============继续================ [root@localhost ~]# a=192.168.1.2-$a [root@localhost ~]# b='192.168.1.2-$a' [root@localhost ~]# c="192.168.1.2-$a" [root@localhost ~]# echo "a=$a" [root@localhost ~]# echo "b=$b" [root@localhost ~]# echo "c=${c}" 此时a,b,c: a=192.168.1.2-192.168.1.2 b=192.168.1.2-$a c=192.168.1.2-192.168.1.2-192.168.1.2 第一种定义a变量的方式:直接定义变量内容 ,内容一般为简单连续的数字,字符串,路径名等 第二种定义b变量的方式:通过单引号定义变量。特点:所见即所得。输出变量时引号里是什么就输出什么,即使内容 中有变量也会把变量名原样输出。此法比较适合于定义显示纯字符串 第三种定义c变量的方式:通过双引号定义变量。特点:输出变量是引号里的变量会经过解析后输出该变量内容,而不是把引号中变量 名原样输出,适合于字符串中附带有变量的内容的定义。
[root@localhost ~]# NUM=123 [root@localhost ~]# awk 'BEGIN {print '$NUM'}' 123 [root@localhost ~]# awk 'BEGIN {print "$NUM"}' $NUM
A. 用户变量 由用户自定义变量名和变量的值 B. 环境变量 主要保存的是和系统环境相关的数据(如:当前登录用户,用户的家目录,命令的提示符)。 包括两部分:一是,由系统设置的(HOME,PATH,SHELL) 二是,用户在命令行中设置的,使用export命令,但是用户注销时值将丢失 C.位置参数变量
主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的 D.预定义变量
是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的
env和命令的区别:
set命令:
可以查看所有变量
env命令:
只能查看环境变量
A.用户变量
变量调用: echo $变量名 变量查看: set [选项] -u :调用没有声明的变量时会报错 -x :命令执行前,会先把命令输出一次 #直接set 回车,是显示系统中所有的变量(自定义、系统等) 变量删除 unset 变量名
B.环境变量
环境变量设置: export name=Tomcat 环境变量查询和删除 查看:env和set的区别:set命令可以查看所有变量,而env命令只能查看环境变量 删除:unset
1. 系统默认的环境变量
env命令可以查询到所有的环境变量,可是还有一些变量虽然不是环境变量,却是和Bash操作接口相关的变量,这些变量也对我们的Bash操作终端起到了重要的作用。这些变量就只能
用set命令来查看了。
2. PATH变量:系统查找命令的路径

PATH变量的值是用“:”分割的路径,这些路径就是系统查找命令的路径。也就是说当我们输入了一个程序名,如果没有写入路径,系统就会到PATH变量定义的路径中去寻找,是否有可以执行的程序。如果找到则执行,否则会报“命令没有发现”的错误。
我们可以考虑把自己写的脚本放入这些目录,实现直接调用(当命令使用)

或者:
修改PATH变量的值,而不是把程序脚本复制到/bin/目录中,以后所有写入这个目录的脚本都可以直接执行(临时)

3. PS1变量:命令提示符设置
PS1是用来定义命令行的提示符
PS1支持的选项:
\d:显示日期,格式为“星期月日” \H:显示完整的主机名。如默认主机名“localhost.localdomain” \h:显示简写主机名。如默认主机名“localhost” \t:显示24小时制时间,格式为“HH:MM:SS” \T:显示12小时制时间,格式为“HH:MM:SS” \A:显示24小时制时间,格式为“HH:MM” \@:显示12小时制时间,格式为“HH:MM am/pm” \u:显示当前用户名 \v:显示Bash的版本信息 \w:显示当前所在目录的完整名称 \W:显示当前所在目录的最后一个目录 \#:执行的第几个命令 \$:提示符。如果是root提示符为“#”,如果是普通用户提示符为“$”
定义规范(定义PS1的值,需要注意单引号,否则不生效)

4.LANG语系变量
LANG定义的是Linux的主语系环境变量

因为我们Linux安装时,选择的是中文安装,所以默认的主语系变量是“zh_CN.UTF-8”。
Linux中支持的语系,使用以下命令查询:
[root@localhost ~]#locale -a |wc -l 735
当前语系:
用locale 直接查询
默认语系配置文件:
CentOS6:

CentOS7:
/etc/locate.conf LANG="en_US.UTF-8"
默认语系和当前语系:
默认语系: 下次重启之后系统所使用的语系 当前系统语系: 当前系统使用的语系 如果系统重启,会从默认语系配置文件/etc/sysconfig/i18n 中读出语系,然后赋予变量LANG让这个语系生效。也就是,LANG定义的语系只对当前系统生效,要想永久生效就要修改
/etc/sysconfig/i18n文件
补充:
是不是我们只要定义了语系为中文语系,如zh_CN.UTF-8就可以正确显示中文了呢?这要分情况,如果我们是在图形界面中,或者是使用远程连接工具(如SecureCRT),只要正确设置了语系,那么是可以正确显示中文的。当然远程连接工具也要配置正确的语系环境。
那么如果是纯字符界面(本地终端tty1 -tty6)是不能显示中文的,因为Linux的纯字符界面时不能显示中文这么复杂的编码的。如果我们非要在纯字符界面显示中文,那么只能安装中文插件,如zhcon等。
C.位置参数变量

1. $0 获取当前执行shell脚本的文件名,包括路径
2.打印 $1-$10
方法1: [root@localhost ~]# seq -s " $" 1 10|sed '/1/s/1/$1/' $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 方法2 [root@localhost ~]# seq 9 |sed 's#[0-9]#$&#g' #竖着显示
3.当要执行的脚本为全路径时,此时,$0 也会带着路径。若 希望取出 路径和文件名(dirname,basename)
[root@localhost tmp]# cat test.sh dirname $0 basename $0 [root@localhost tmp]# bash /tmp/test.sh /tmp test.sh
4. $*和$@的区别示例:
$* 将所有的命令行参数视为 单个字符串,等同于 "$1$2$3" $@ 将命令行每个参数视为 单独的字符串,等同于 "$1" "$2" "$3"。这里将参数传递给其他程序的最佳方式,因为它会保留所有内嵌在每个参数的任何空白
[root@localhost ~]# set -- "I am" little tomcat #设置三个字符串参数,“--” 表示清除所有的参数变量,重新设置后面的参数变量 [root@localhost ~]# echo $# 3 [root@localhost ~]# for i in $*;do echo $i;done #循环打印这些参数,用$*,无引号 I am little tomcat [root@localhost ~]# for i in $@;do echo $i;done #在没有双引号的情况下,这里的结果 $*和$@是一样的 I am little tomcat [root@localhost ~]# for i;do echo $i;done #去掉 in 变量列表,相当于 in “$@” I am little tomcat [root@localhost ~]# [root@localhost ~]# for i in "$@";do echo $i;done #有双引号 I am little tomcat [root@localhost ~]# for i in "$*";do echo $i;done #加了双引号,$*表示 一个字符串,参数里引号内容当做一个参数输出了,这才真正符合传入的参数需求,set -- "I am" little tomcat I am little tomcat [root@localhost ~]# shift #使用shift去掉第一参数 [root@localhost ~]# echo $# 2 [root@localhost ~]# for i in "$@";do echo $i;done #再次打印只剩后面两个参数了 little tomcat [root@localhost ~]# for i in "$*";do echo $i;done little tomcat [root@localhost ~]# for i;do echo $i;done little tomcat [root@localhost ~]# for i in $*;do echo $i;done little tomcat
D.预定义变量

1. $? 返回值
0 表示运行成功 2 权限拒绝 1~125 表示运行失败,脚本命令,系统命令错误或参数传递错误 126 找到该命令,但是无法执行 127 未找到要运行的命令 >128 命令被系统强制结束
2. $_
在此之前执行的命令或脚本的最后一个参数
bash内部变量
有些内部变量在目录列表是是看不见的,它们有Shell本身提供。 常用内部命令:echo,export,read,exit 其次:eval,exec,shift,点(.)
echo 变量名表
将变量名表指定的变量显示到标准输出
eval args
读入参数args,并将它们组合成一个新的命令,然后执行
exec 命令参数
当Shell执行到exec语句是,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程(也就是当初的Shell)也就终止了,所以Shell程序中exec后面
的语句将不再被执行。
export 变量名=value
Shell 可以用export 把它的变量向下带入子Shell,从而让子进程继承父进程中的环境变量。但子Shell不能用export把它的变量向上带入父Shell
read 变量名表
从标准输入读字符串,传给指定变量.可以在函数中用local 变量名 的方式申明局部变量。
read [选项] [变量名] -p “提示信息”:在read等待时输入的信息 -t 秒数 :read等待的秒数 -n 字符数:read最多能接收的字符数(达标即执行) -s 隐藏输入信息
[root@localhost test]# vim read.sh #!/bin/bash read -p "Please input your name:" name echo $name read -t 20 -p "Please input your age:" age echo $age read -s -t 20 -p "Please input your sex(m/x):" sex echo "" #因为特殊选项不换行,用echo 来实现换行。 echo $sex
shift 语句
shift语句按如下方式重新命令所有的位置参数变量,即$2称为$1,$3称为$2。在程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,并使
位置参数$# 减1,直到减到0为止。
[root@localhost ~]# set -- "I am" little tomcat [root@localhost ~]# echo $1 I am [root@localhost ~]# echo $2 little [root@localhost ~]# echo $3 tomcat [root@localhost ~]# shift [root@localhost ~]# echo $1 little [root@localhost ~]# echo $2 tomcat [root@localhost ~]# shift [root@localhost ~]# echo $1 tomcat [root@localhost ~]# echo $2 #为空 [root@localhost ~]#
[root@localhost ~]# vim /usr/bin/ssh-copy-id #!/bin/sh ID_FILE="${HOME}/.ssh/id_rsa.pub" if [ "-i" = "$1" ]; then shift #!!!!!! # check if we have 2 parameters left, if so the first is the new ID file if [ -n "$2" ]; then if expr "$1" : ".*\.pub" > /dev/null ; then ID_FILE="$1" else ID_FILE="$1.pub" fi shift # and this should leave $1 as the target name fi else if [ x$SSH_AUTH_SOCK != x ] ; then GET_ID="$GET_ID ssh-add -L" fi fi
计算变量长度的不同方法以及不用方法的耗时对比
[root@localhost ~]# chars=`seq -s " " 100` [root@localhost ~]# echo ${#chars} 291 [root@localhost ~]# echo $chars|wc -m 292 [root@localhost ~]# echo $(expr length "$chars") 291 [root@localhost ~]# time for i in $(seq 10000);do count=${#chars};done real 0m1.795s user 0m1.740s sys 0m0.054s [root@localhost ~]# time for i in $(seq 10000);do count=`echo ${chars} |wc -m`;done real 0m34.413s user 0m7.292s sys 0m11.386s [root@localhost ~]# [root@localhost ~]# time for i in $(seq 10000);do count=`echo expr length "${chars}"`;done real 0m10.306s user 0m1.833s sys 0m3.000s #一般情况下,用外部命令处理,与内置功能操作性能相差较大。在shell编程中,应尽量用内置操作或函数完成
变量名定义:
变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY
如果只提供了一个变量名,则整个输入行赋予该变量
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有值
示例: [root@localhost test]# cat test.sh #!/bin/bash read -p "Please input your name:" read -p "Please input your test:" test echo $test read -p "Please input your num:" a b c echo $a echo $b echo $c 运行: [root@localhost test]# bash test.sh Please input your name:Tomcat Please input your test:A B C A B C Please input your num:1 2 3 4 5 1 2 3 4 5 #最后一个变量取得剩余的所有值
二 Shell 运算符
数值运算方法:
使用declare声明变量类型 命令:declare [+/-] [选项] 变量 - : 给变量设定类型 + : 取消变量的类型 -a : 将变量声明成数组型 -i : 将变量声明成整数型 -r : 将变量声明成只读(变量值不能修改,也不能删除,更不能取消只读选项) -x : 将变量声明成环境变量 -p : 显示指定变量的类型及内容
变量的数值计算常见的命令:
(()),let,expr,bc,$[]
1. (())
要执行简单的整数运算,只需将特定的算数表达式用 $(( )) 括起来
shell的算数运算符号常置于 $(( )) 的语法中。这一语法如同双引号功能,除了内嵌双引号无需转义。
例1:shell的算数运算:
[root@localhost ~]# ((a=1+2**3-4%3)) [root@localhost ~]# echo $a 8 [root@localhost ~]# b=$((1+2**3-4%3)) [root@localhost ~]# echo $b 8 [root@localhost ~]# echo $((1+2**3-4%3)) 8
例2:--,++ 在变量前后
[root@localhost ~]# c=6 [root@localhost ~]# echo $((c++)) #c在前面,先打印 c,在自增1 6 [root@localhost ~]# echo $c 7 [root@localhost ~]# echo $((c++)) 7 [root@localhost ~]# echo $c 8 [root@localhost ~]# d=10 [root@localhost ~]# echo $((++d)) #先计算,在赋值 11 [root@localhost ~]# echo $d 11 [root@localhost ~]# echo $((--d)) 10 [root@localhost ~]# echo $d 10 提示:变量在前,先输出变量值,变量在后,就是先运算后输出变量的值
[root@localhost ~]# echo $((100*(100+1)/2)) 5050
例3:定义变量计算
[root@localhost ~]# num=99 [root@localhost ~]# echo $(($num + 1)) 100 [root@localhost ~]# echo $(( $num + 1 )) # (( )) 两边有几个空格不明感,也可以没有 100 [root@localhost ~]# num=$(( $num + 1 )) #还可以赋值给变量然后输出变量 [root@localhost ~]# echo $num 100
例4:各种 (( ))的计算命令
[root@localhost ~]# echo $(( 100 / 5 )) #除法 去商数 20 [root@localhost ~]# echo $(( 100 / 30 )) 3 [root@localhost ~]# echo $(( 10 ** 3 )) #幂 1000 [root@localhost ~]# echo $(( 100 % 5 )) #取模,余数 0 [root@localhost ~]# echo $(( 100 % 30 )) 10
例5:各种(( )) 运算的shell脚本例子
[root@localhost test]# cat test.sh #!/bin/bash a=6 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 ))" echo "a%b =$(( $a % $b ))" [root@localhost test]# bash test.sh a-b =4 a+b =8 a*b =12 a/b =3 a**b =36 a%b =0
命令行传参:
[root@localhost test]# cat test.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 ))" echo "a%b =$(( $a % $b ))"
简单计算器:
[root@localhost test]# cat tc.sh echo $(($1$2$3)) [root@localhost test]# bash tc.sh 3*3 9
let 命令
格式: let 赋值表达式 提示:let赋值表达式功能等同于:((赋值表达式)) 但效率比 (( )) 低
例1: 自变量i加8
[root@localhost ~]# i=2 [root@localhost ~]# let i=i+8 [root@localhost ~]# echo $i 10 [root@localhost ~]# [root@localhost ~]# i=i+8 #去掉let定义 [root@localhost ~]# echo $i i+8 #输出的结果
expr(evaluate expressions)命令
expr命令一般用于整数值,但也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令行计算器。
例一:
[root@localhost ~]# expr 2 + 2 4 [root@localhost ~]# expr 2 - 2 0 [root@localhost ~]# expr 6-3 6-3 [root@localhost ~]# expr 2 * 3 expr: 语法错误 [root@localhost ~]# expr 2 \* 3 6 提示: 1.运算符左右都有空格 2. 使用乘号,必须用反斜线屏蔽其特定含义。因shell可能会误解星号的含义
例2:给自变量i 加1
[root@localhost ~]# i=0 [root@localhost ~]# i=`expr $i + 1` #效率低 [root@localhost ~]# echo $i 1
expr $[$a+$b]表达式形式,其中$a$b可为整数值
[root@localhost ~]# a=5 [root@localhost ~]# b=6 [root@localhost ~]# expr $[$a+$b] 11 [root@localhost ~]# expr $[ $a+$b ] 11 [root@localhost ~]# expr $[ $a + $b ] 11 [root@localhost ~]# expr $[ $a + $b ] 11
expr 系统中的用法 /usr/bin/ssh-copy-id
if [ -n "$2" ]; then if expr "$1" : ".*\.pub" > /dev/null ; then #expr id_dsa.pub : '.*\.pub',匹配 *.pub 格式的文件如果是则为真。 ID_FILE="$1" else ID_FILE="$1.pub" fi shift # and this should leave $1 as the target name fi
技巧:判断文件或字符串的扩展名
[root@localhost ~]# expr "test.txt" : ".*\.txt" && echo 1 ||echo 0 8 #匹配后的字符数量 1 [root@localhost ~]# expr "abc.sh" : ".*\.txt" && echo 1 ||echo 0 0 0
技巧:通过expr判断变量是否为整数
[root@localhost ~]# cat judge_int.sh read -p "Pls input:" a expr $a + 0 &>/dev/null [ $? -eq 0 ] && echo int ||echo chars [root@localhost ~]# [root@localhost ~]# bash judge_int.sh Pls input:123 int [root@localhost ~]# bash judge_int.sh Pls input:TEST chars
持续等待输入连续判断
[root@localhost ~]# cat judge_int.sh #!/bin/bash while true do read -p "Pls input:" a expr $a + 0 >/dev/null 2>&1 [ $? -eq 0 ] &&echo int ||echo chars done
bc命令
bc 是UNIX下的计算器,也可以用在命令行下面 bc特点:支持小数运算
[root@localhost ~]# i=2 [root@localhost ~]# echo $i+1 2+1 [root@localhost ~]# echo $i+1 |bc #效率低 3
#因为bc支持科学计算,所有这种方法功能非常强大
例1:
[root@localhost ~]# echo 3.5+3|bc 6.5 [root@localhost ~]# echo 6.6-3.5|bc 3.1 [root@localhost ~]# echo "obase=2;8"|bc #10进制8转换成2进制 1000 [root@localhost ~]# echo "obase=16;20"|bc #十进制20转换成16进制、 14 [root@localhost ~]# echo 10/3 |bc 3 [root@localhost ~]# [root@localhost ~]# echo "scale=2;10/3" |bc #保留两位小数 3.33
shell的变量输入内置read命令
Shell变量除了可以直接赋值或脚本传参外,还可使用read命令从标准输入获得
ead [选项] [变量名]
-p “提示信息”:在read等待时输入的信息
-t 秒数 :read等待的秒数
-n 字符数:read最多能接收的字符数(达标即执行)
-s 隐藏输入信息
例1:
[root@localhost test]# vim read.sh #!/bin/bash read -p "Please input your name:" name echo $name read -t 20 -p "Please input your age:" age echo $age read -s -t 20 -p "Please input your sex(m/x):" sex echo "" #因为特殊选项不换行,用echo 来实现换行。 echo $sex
例2:read简单计算
[root@localhost ~]# cat num.sh #!/bin/bash read -p "Pls input num:" 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 ))" echo "a%b =$(( $a % $b ))" [root@localhost ~]# bash num.sh Pls input num:3 3 a-b =0 a+b =6 a*b =9 a/b =1 a**b =27 a%b =0
例3:利用echo 命令代替 read -p的功能
[root@localhost test]# cat test.sh #!/bin/bash echo -n "Pls input two number:" #-n 不换行 read 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 ))" echo "a%b =$(( $a % $b ))" [root@localhost test]# bash test.sh Pls input two number:3 3 a-b =0 a+b =6 a*b =9 a/b =1 a**b =27 a%b =0
例4:判断输入的数字是否是 整数 !!
[root@localhost test]# cat test.sh
#!/bin/bash read -p "Pls input two number:" a b while true do read -p "Pls input two number:" a b expr $a + 0 >/dev/null 2>&1 [ $? -ne 0 ] && continue expr $b + 0 >/dev/null 2>&1 [ $? -ne 0 ] && contiune ||break done 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 ))" echo "a%b =$(( $a % $b ))"
例5:使用函数,计算器
[root@localhost test]# cat test.sh #!/bin/bash a="$1" b="$2" Usage(){ echo "bash $0 num1 num2" exit 1 } if [ $# -ne 2 ];then Usage fi expr $a + 0 >/dev/null 2>&1 [ $? -ne 0 ] && Usage expr $b + 0 >/dev/null 2>&1 [ $? -ne 0 ] && Usage 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 ))" echo "a%b =$(( $a % $b ))"

浙公网安备 33010602011771号