Linux之bash变量和逻辑运算

什么是变量?

变量最初来源于数学,指的是非固定的值可变化的数通常用拉丁字母表示。在计算机中变量它依旧指的是可变化的数,只不过表现形式有些变化。它指的是变量名+所指向的内存空间

变量的特点

变量分强类型变量,与弱类型变量

强类型变量:变量需事先声明且需提前定义其变量存储格式

弱类型变量:不需事先声明,不需定义变量存储格式。

bash把所有变量统统视作字符型;bash中的变量无需事先声明,相当于,把声明和赋值过程同时实现。

变量名的命名规范

变量名只能包含数字字母下划线,而且不能以数字开头

其命名要求见名知义,命名机制遵循某种法则(驼峰法则)不能使用程序的保留字:if,else,then,while,for...


 

bash的变量类型及其使用格式

本地变量,环境变量,局部变量,位置参数变量,特殊变量

变量引用格式:$VAR、${VAR}

………………………………………………………………………………………………………………………

本地变量:作用域仅为当前shell进程

变量赋值:name=‘value’

value有如下引用类型

1、直接字符串引用,格式name="CHARS"

1

2

3

[root@centos7 ~]# name1=abc

[root@centos7 ~]# echo $name1 

abc

2、变量引用,格式:name=“$VAR”

1

2

3

[root@centos7 ~]# name2=$SHELL

[root@centos7 ~]# echo $name2

/bin/bash

3、命令引用,格式:name=`COMMAND` | name=$(COMMAND)

1

2

3

4

5

6

[root@centos7 ~]# name3=`date`

[root@centos7 ~]# echo $name3

2016年 08月 14日 星期日 11:16:55 CST

[root@centos7 ~]# name3=$(date)

[root@centos7 ~]# echo $name3

2016年 08月 14日 星期日 11:17:11 CST

“”:弱引用,其中的变量引用会被替换为变量值;

1

2

3

[root@centos7 ~]# name4="$name1"

[root@centos7 ~]# echo $name4

abc

‘’:强引用,其中的变量引用不会被替换为变量值,而保持原字符串;

1

2

3

[root@centos7 ~]# name5='$name1'

[root@centos7 ~]# echo $name5

$name1

命令set用于显示已定义的所有变量

撤销已定义的变量,格式:unset 变量名

1

2

3

4

5

[root@centos7 ~]# echo $name5

$name1

[root@centos7 ~]# unset name5

[root@centos7 ~]# echo $name5

[root@centos7 ~]#

在刚接触bash变量时特别容易搞错的就是变量的使用格式,有时候该命令引用却忘记加``或$(),还有就是强引用与弱引用的使用时机。

下面以例子说明本地变量的作用范围,使用命令bash进入子shell

1

2

3

4

5

6

7

[root@centos7 ~]# bash

[root@centos7 ~]# echo $name1

  

[root@centos7 ~]# exit

exit

[root@centos7 ~]# echo $name1

abc

由实验可知,作用域仅为当前shell进程。当然上面实验做的不够完善,因为并没有演示在符父shell中其变量是否有效,大家可以在下面补充实验去验证。

………………………………………………………………………………………………………………………

环境变量:作用域为当前shell进程及子进程

变量赋值:

有四种赋值格式:

    1、export name=value

    2、name=value

       export name

    3、declare -x name=value

    4、name=value

       declare -x name

:bash内嵌了许多环境变量(通常全为大写字符),用于定义bash的工作环境

查看/显示环境变量 命令

export

1

2

3

4

5

6

[root@centos7 ~]# export | head -5

declare -x HISTCONTROL="ignoredups"

declare -x HISTSIZE="1000"

declare -x HOME="/root"

declare -x HOSTNAME="centos7"

declare -x LANG="zh_CN.UTF-8"

declare -x

1

2

3

4

5

6

[root@centos7 ~]# export | head -5

declare -x HISTCONTROL="ignoredups"

declare -x HISTSIZE="1000"

declare -x HOME="/root"

declare -x HOSTNAME="centos7"

declare -x LANG="zh_CN.UTF-8"

printenv

1

2

3

4

5

6

[root@centos7 ~]# printenv | head -5

XDG_SESSION_ID=8

HOSTNAME=centos7

SELINUX_ROLE_REQUESTED=

TERM=linux

SHELL=/bin/bash

env

1

2

3

4

5

6

[root@centos7 ~]# printenv | head -5

XDG_SESSION_ID=8

HOSTNAME=centos7

SELINUX_ROLE_REQUESTED=

TERM=linux

SHELL=/bin/bash

上面四个命令虽然显示顺序略有不同但是所包含的内容都是一样的

1

2

3

4

5

6

7

8

[root@centos7 ~]# env | wc -l

24

[root@centos7 ~]# printenv | wc -l

24

[root@centos7 ~]# export | wc -l       

24

[root@centos7 ~]# declare -x | wc -l     

24

撤销环境变量

格式:unset VAR

下面通过例子验证环境变量的作用范围

1

2

3

4

5

6

[root@centos7 ~]# export name6=$name2

[root@centos7 ~]# echo $name6

/bin/bash

[root@centos7 ~]# bash

[root@centos7 ~]# echo $name6

/bin/bash

………………………………………………………………………………………………………………………

局部变量:作用域仅为某代码片段(通常用在函数)

因为函数还没学到,这里不举例子

………………………………………………………………………………………………………………………

位置变量:当执行脚本的shell进程传递的参数

$1,$2,...$(10)...:对应调用第1,第2...第10个参数

………………………………………………………………………………………………………………………

特殊变量:shell内置的特殊功用的变量

$#:传递给脚本参数的个数

$*:传递给脚本的所有参数;各参数读成多个独立字符串

$@:传递给脚本的所有参数;各参数读成一个完整的字符串形式

$?:程序执行状态返回值,0表示正确,1-255表示失败
$0:表示命令本身

算术运算

Linux中的运算符主要有单目运算符和双目运算符,运算符也有优先级的高低之分。

运算符主要有以下这些:

优先级 运算符 类型 说明
13 +、- 单目 单目正、单目负。它们是单目运算符的正、负,而不是加、减。
12 !、~ 单目 逻辑非、按位取反或补码。
11 *、/、% 双目 乘、除、取模。
10 +、- 双目 加、减。
9 <<、>> 双目 按位左移、按位右移。
8 <、<=、>、>= 双目 小于、小于等于、大于、大于等于。
7 ==、!= 双目 等于、不等于。
6 & 双目 按位与。
5 ^ 双目 按位异或。
4 | 双目 按位或。
3 && 双目 逻辑与。
2 || 双目 逻辑或。
1 =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>= 双目 赋值、运算且赋值。

说明:对于该表,数值越大,优先级越高。故赋值运算符的优先级最低。

注意: 小括号内的表达式的优先级最高,会优先运算。因此,可以用小括号改变运算符的优先级。

优先级越高,会先进行运算;相同优先级的运算符,按照先后顺序顺序运算。

--------------------- 本文来自 lamp_yang_3533 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/lamp_yang_3533/article/details/70041211?utm_source=copy

在未学习bash中的算术运算之前如果要计算从1+...+10需要使用管道将其送入bc计算器来解决,

echo {1..10} | tr ' ' '+'| bc很麻烦。而使用bash中的算术运算则可以简化代码。

bash中的算术运算格式:有很多种,本文只介绍常用的4种

1)let VAR=算术运算表达式

1

2

3

[root@centos7 test]# let sum1=1+10

[root@centos7 test]# echo $sum1

11

2)VAR=$[算术表达式]

1

2

3

[root@centos7 test]# sum2=$[2+2]

[root@centos7 test]# echo $sum2

4

3)VAR=$((算术表达式))

1

2

3

[root@centos7 test]# sum3=$((5+5))

[root@centos7 test]# echo $sum3

10

4)VAR=$(expr $ARG $OP $ARG2)

1

2

3

4

5

6

[root@centos6 ~]# sum4=$(expr 2+8)

[root@centos6 ~]# echo $sum4

2+8

[root@centos6 ~]# sum4=$(expr 2 + 8 )

[root@centos6 ~]# echo $sum4

10

这种是调用expr命令计算后面运算表达式,它要求数值与运算符之间有空格,没有空格则不进行计算,保持运算表达式原本模样赋值给变量。

:它与上述三种不同之处还有如果有乘法运算,乘法符号*在第四种里面需要加\进行转义。

以下为四种算术运算在乘法中的表现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[root@centos6 ~]# sum4=$(expr 2 * 8 )

expr: 语法错误

[root@centos6 ~]# sum4=$(expr 2 \* 8 )

[root@centos6 ~]# echo $sum4

16

[root@centos6 ~]# let sum1=6*6

[root@centos6 ~]# echo $sum1

36

[root@centos6 ~]# sum2=$[2*3]

[root@centos6 ~]# echo $sum2

6

[root@centos6 ~]# sum3=$((3*4))

[root@centos6 ~]# echo $sum3

12

第四种需要转义,其他三种不需要。

逻辑运算符

逻辑卷标 表示意思
1. 关于档案与目录的侦测逻辑卷标!
-f 常用!侦测『档案』是否存在 eg: if [ -f filename ]
-d 常用!侦测『目录』是否存在
-b 侦测是否为一个『 block 档案』
-c 侦测是否为一个『 character 档案』
-S 侦测是否为一个『 socket 标签档案』
-L 侦测是否为一个『 symbolic link 的档案』
-e 侦测『某个东西』是否存在!
2. 关于程序的逻辑卷标!
-G 侦测是否由 GID 所执行的程序所拥有
-O 侦测是否由 UID 所执行的程序所拥有
-p 侦测是否为程序间传送信息的 name pipe 或是 FIFO (老实说,这个不太懂!)
3. 关于档案的属性侦测!
-r 侦测是否为可读的属性
-w 侦测是否为可以写入的属性
-x 侦测是否为可执行的属性
-s 侦测是否为『非空白档案』
-u 侦测是否具有『 SUID 』的属性
-g 侦测是否具有『 SGID 』的属性
-k 侦测是否具有『 sticky bit 』的属性
4. 两个档案之间的判断与比较 ;例如[ test file1 -nt file2 ]
-nt 第一个档案比第二个档案新
-ot 第一个档案比第二个档案旧
-ef 第一个档案与第二个档案为同一个档案( link 之类的档案)
5. 逻辑的『和(and)』『或(or)』
&& 逻辑的 AND 的意思
|| 逻辑的 OR 的意思

  

逻辑表达式

 

  • test 命令

使用方法:test EXPRESSION

如:

[root@localhost ~]# test 1 = 1 && echo 'ok'
ok

[root@localhost ~]# test -d /etc/ && echo 'ok' 
ok

[root@localhost ~]# test 1 -eq 1 && echo 'ok'
ok

 

[root@localhost ~]# if test 1 = 1 ; then echo 'ok'; fi
ok

 

注意:所有字符 与逻辑运算符直接用“空格”分开,不能连到一起。

 

  • 精简表达式
  • [] 表达式

[root@localhost ~]# [ 1 -eq 1 ] && echo 'ok'           
ok

[root@localhost ~]# [ 2 < 1 ] && echo 'ok'                  
-bash: 2: No such file or directory

 

[root@localhost ~]# [ 2 \< 1 ] && echo 'ok'

[root@localhost ~]# [ 2 -gt 1 -a 3 -lt 4 ] && echo 'ok'

ok    

[root@localhost ~]# [ 2 -gt 1 && 3 -lt 4 ] && echo 'ok'   
-bash: [: missing `]'

注意:在[] 表达式中,常见的>,<需要加转义字符,表示字符串大小比较,以acill码 位置作为比较。 不直接支持<>运算符,还有逻辑运算符|| && 它需要用-a[and] –o[or]表示

 

 

 

  • [[]] 表达式
[root@localhost ~]# [ 1 -eq 1 ] && echo 'ok'           
ok

[root@localhost ~]$ [[ 2 < 3 ]] && echo 'ok' 
ok

[root@localhost ~]$ [[ 2 < 3 && 4 > 5 ]] && echo 'ok' 
ok

注意:[[]] 运算符只是[]运算符的扩充。能够支持<,>符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| &&

 

 

三、性能比较

bash的条件表达式中有三个几乎等效的符号和命令:test,[]和[[]]。通常,大家习惯用if [];then这样的形式。而[[]]的出现,根据ABS所说,是为了兼容><之类的运算符。以下是比较它们性能,发现[[]]是最快的。


$ time (for m in {1..100000}; do test -d .;done;)
real    0m0.658s
user    0m0.558s
sys     0m0.100s


$ time (for m in {1..100000}; do [ -d . ];done;)
real    0m0.609s
user    0m0.524s
sys     0m0.085s


$ time (for m in {1..100000}; do [[ -d . ]];done;)
real    0m0.311s
user    0m0.275s
sys     0m0.036s


不考虑对低版本bash和对sh的兼容的情况下,用[[]]是兼容性强,而且性能比较快,在做条件运算时候,可以使用该运算符。

猜你喜欢

转载自blog.csdn.net/qq_41675254/article/details/82933634
今日推荐