Linux学习笔记----第七章

1.shell脚本语言

1.1基本结构

  • shell是基于过程式、解释执行的语言

  • shell脚本是包含一些命令或声明,并符合一定格式的文本文件

  • 首先必须符合shebang机制的格式要求:

#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
#!/usr/bin/ruby
#!/usr/bin/lua

1.2shell脚本的注释规范

一般要注明作者,创建(修改)时间,文件名,版本号,该程序的功能及作用,目地,版权信息,作者联系方式等

1.3shell脚本执行

#使用bash,是在shell脚本文件没有执行权限的情况下
$ bash test1.sh
    
#管道
$ cat test1.sh | bash
    
#重定向
$ bash < test1.sh
$ bash <<< $(cat test1.sh)  #<<<,就是把其后面的内容以一个单一字符串并加上换行符,发送到命令的标准输入或者文件描述符n中

#当shell脚本文件具有执行权限,或给shell脚本增加了执行权限
#绝对路径
$ /opt/test1.sh

#相对路径,也是在子进程中执行的
$ ./test1.sh
    
#在当前进程中执行
$ . test1.sh

1.4shell脚本调试

#检测脚本中的语法错误,不能检测命令错误,也不会执行脚本
$ bash -n cp.sh 

#逐行输出命令,并输出执行结果
$ bash -x test1.sh


#语法错误:会导致后续的命令不继续执行,可以用 bash -n 检查错误,提示的出错行数不一定是准确的
#命令错误:默认后续的命令还会继续执行,用 bash -n 无法检查出来 ,可以使用 bash -x 进行观察
#逻辑错误:只能使用 bash -x 进行观察

1.5变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据数据要存在内存空间中,而内存空间又是通过内存地址来访问的,但内存地址一般是16进制的编号;为了方便使用,就有了变量名,当访问一个变量时,实际是访问其对应的内存地址的那块内存空间。

1.5.1普通变量
#变量赋值
$ name="zhangsan" 				#直接字串
$ name="$USER" 					#变量引用,双引号为弱引用,可以识别变量,单引号是强引用,里面内容是什么,输出的内容就是什么
$ name=`ll -d /etc/passwd` 		#命令引用
$ name=$(ll -d /etc/passwd) 	#命令引用
    
#变量引用,若要保留数据的格式,对引用的变量加上双引号("")
$ echo $name
$ echo ${name}

#显示已定义的所有变量
$ set
    
#删除变量
$ unset name
    
#普通变量的生效范围只在当前shell进程,相对于当前shell的其它shell进程,以及当前shell进程的子shell进程,普通变量都是无效的
1.5.2环境变量  
#变量声明和赋值
$ export name=zhangsan
$ declare -x name=zhangsan
    
#显示所有环境变量
$ printenv
$ env
$ export
$ declare -x
    
#查看当前进程的环境变量
$ cat /proc/$$/environ | tr "\0" "\n"  #$$表示当前进程的PID,字符串是以"\0"结尾,以换行"\n"对其进行替换
1.5.3只读变量
#只能声明定义,但后续不能修改和删除,即常量
#声明只读变量和赋值,退出当前进程后,设置的只读变量就会失效
$ readonly PI=3.14
$ declare -r PI=3.14
    
#查看声明的只读变量
$ readonly
$ declare -r
1.5.4位置变量
#bash shell中内置的变量,通过命令行传递给脚本的参数
$1,$2,... 	#对应第1个、第2个等参数,shift [n]换位置
$0 			#命令本身,包括路径
$* 			#传递给脚本的所有参数,全部参数合为一个字符串
$@ 			#传递给脚本的所有参数,每个参数为独立字符串
$# 			#传递给脚本的参数的个数
    
#清空所有位置变量
$ set --
1.5.5退出状态码变量
#进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255
$ echo $?    #0表示命令执行成功,1-255表示执行失败
    
#用户可以在脚本中自定义退出状态码
exit num
    
#脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
#如果exit后面无数字,终止退出状态取决于exit命令前面命令执行结果
#如果没有exit命令,即未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
1.5.6脚本安全和set
#set命令,可以用来定制 shell 环境
#查看命令行下的$-变量
$ echo $-
himBHs	#h:hash表,B:大括号扩展
    
#关闭大括号扩展
$ set +B
    
#启用大括号扩展
$ set -B
    
    
#set命令实现脚本安全,+是禁止,-是开启
#显示所有
$ set -o
    
#开启此项,在使用一个没有声明的变量时,会报错,并且终止程序
$ set -o nounset	#同set -u
    
#开启此项,命令返回非0就退出,不再继续执行后面的代码
$ set -o errexit	#同set -e

1.6格式化输出printf

#相对于echo,有着更为丰富的输出格式
$ printf format args...

#常用的格式替换符,也就是format
%s		#字符串
%d|%i	#十进制整数
%u		#不带正负号的十进制
%f		#浮点数
%c		#ASCII字符,显示对应参数的第一个字符
%b		#相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
%o		#八进制
%X		#十六进制值(A-F)
%x		#十六进制值(a-f)
%%		#百分号%本身
    
%[N]s 		# N表示输出宽度,不够补空格 -N 表示左对齐
%[0][N]d 	# 0表示宽度不够时在左边补0,N表示输出宽度
%[.N]f 		# .N 表示保留的小数位
    
#常用转义字符
\a		#警告字符,通常为ASCII的BEL字符
\b		#后退
\f		#换页
\n		#换行
\r		#回车
\t		#水平制表符,也就tab键
\v		#垂直制表符
\		#\本身

1.7算术运算符

#括号内赋值:((变量名=整数表达式))
$ ((k=i+j));echo $k
    
#括号外赋值:变量名=$((整数表达式))
$ k=$((i+j));echo $k
    
#变量名=$[表达式]
$ k=$[m=i+j];echo $k $m
$ k=$[i+j];echo $k
    
#let 变量名=表达式
$ let k=i+j;echo $k
    
#expr 表达式:表达式中,每参数与运算符间需要有空格,特殊字符需要转义
$ expr 10 + 20
$ expr 10 \* 20
    
#内建的随机数生成器变量,取值范围:0-32767
$ echo $RANDOM

1.8逻辑运算

1.8.1与或非

&,|,!,^

1.8.2短路运算

&&,||

1.9条件测试命令

test expr
[ arg... ] 			#同 test
[[ expression ]] 	#增加版的[],支持[],支持扩展正则表达式和通配符
#注意:[] 中的表达式,前后要有空格
1.9.1变量测试
-v VAR 		#如果变量被设置为为真
-R VAR 		#如果变量被设置且被引用则为真
1.9.2数值测试
#数字相关 格式 arg1 OP arg2
-eq,-ne,-lt,-le,-gt,-ge 
    
#算术表达式比较
==,!=,<=,>=,<,>
1.9.3字符串测试
#test和[]字符串测试用法
#最好将字符串放在""里面
-z STRING 				#判断字符串是否为空,为空则为真
-n STRING 				#如果字符串不为空则为真
STRING 					#同上
    
#两个字符串变量比较,一定要有空格,如果没有空格,就变成赋值了
STRING1 = STRING2 		#如果 string1 和 string2 字符串相同则为真
STRING1 != STRING2 		#如果 string1 和 string2 字符串不相同则为真
STRING1 < STRING2 		#只比较第一个字符,以字母表顺序来比较,string1在string2 之前则为真,< 要转义
STRING1 > STRING2 		#只比较第一个字符,以字母表顺序来比较,string1在string2 之后则为真, > 要转义

#[[]]字符串测试用法
== 						#左侧字符串是否和右侧的PATTERN相同
						#注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 						#左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
						#注意: 此表达式用于[[ ]]中为扩展的正则表达式
1.9.4文件测试
-a|-e				#判断文件是否存在,存在则为真,建议使用-e
-f					#如果文件存在且为常规文件则为真
-d					#判断是否为目录,是目录则为真
-w|-r|-x			#对文件的权限测试,以用户对文件的实际权限决定,而非文件属性决定
FILE1 -nt FILE2 	#如果 file1 文件新于 file2 文件 则为真(根据修改日期)
FILE1 -ot FILE2 	#如果 file1 文件旧于 file2 文件则为真
FILE1 -ef FILE2 	#如果 file1 文件是 file2 文件的硬链接则为真
-s FILE 			#如果文件存在且不为空则为真
#通过chattr对文件的属性进行修改,也会对文件的书写权限有作用

1.10关于()和{}

  • ( cmd1;cmd2;... ) 和 { cmd1;cmd2;...; } 都可以将多个命令组合在一起,批量执行

  • ( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境,但内部命令会继承括号外的父进程的变量

  • { list; } 不会开启子shell, 在当前shell中运行,会影响当前shell环境,左侧要有空格,右侧要有;结束

1.11组合测试条件

1.11.1测试命令方式
#-a和-o 需要使用测试命令进行,[[ ]] 不支持,要注意其中的书写格式
[ EXPRESSION1 -a EXPRESSION2 ] 		#并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 		#或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为真
[ ! EXPRESSION ] 					#取反
1.11.2条件表达式方式
COMMAND1 && COMMAND2 	#并且,短路与,代表条件性的AND THEN,如果COMMAND1成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 	#或者,短路或,代表条件性的OR ELSE,如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND 				#非,取反

#&&和||组合使用,&& 要在前,|| 放在后

2.bash shell的配置文件

2.1按生效范围分类

2.1.1全局配置

针对所有用户都有效:

  • /etc/profile

  • /etc/profile.d/*.sh

  • /etc/bashrc ------------------------ /etc/bash.bashrc #ubuntu

2.1.2个人配置

只针对特定用户有效:

  • ~/.bash_profile

  • ~/.bashrc

2.2按shell登录方式分类

2.2.1交互式登录

就是使用账号密码登录或者su - username登录,配置文件生效和执行顺序与代码写在各个文件中的位置有关,举两个例子,

一是写在文件最前面,配置文件生效和执行顺序为:

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

~/ .bash_ profile

~/ .bashrc

/etc/bashrc (此文件执行两次)

二是写在文件最末尾,配置文件生效和执行顺序为:

/etc/profile.d/*.sh

/etc/bashrc

/etc/profile

/etc/bashrc (此文件执行两次)

~/.bashrc

~/.bash_profile

2.2.2非交互式登录

或su username,或图形化界面下打开的终端,或执行脚本,或其他的bash实例,在这种情况下配置文件生效和执行顺序为:

/etc/profile.d/*.sh

/etc/bashrc

~/.bashrc

2.3按功能分类

profile类:定义环境变量,运行命令或脚本

bashrc类:定义命令别名或函数,本地变量

2.4编辑配置文件生效

修改profile和bashrc文件后要生效,有两种方法:

  • 重新启动shell进程

  • source|. 配置文件

2.5bash退出任务

保存在~/.bash_logout文件中(用户),在退出登录shell时运行,可以实现在退出登录时自动备份或清理临时文件等功能

3.流程控制

3.1条件判断

3.1.1选择执行if语句
#单分支
if 判断条件;theh
    条件为真时的执行语句;
fi
    
#双分支
if 判断条件;then
    条件为真时的执行语句;
else
    条件为假时的执行语句;
fi
    
#多分支
if 判断条件1;then
  	条件1为真时的执行语句;
elif 判断条件2;then
    条件2为真时的执行语句;
elif 判断条件3;then
    条件3为真时的执行语句;
....
else
    上面条件都为假时的执行语句;
fi
3.1.2条件判断case语句
case 变量引用 in
    PATH1)
    分支1
    ;;
	PATH2)
    分支2
    ;;
	....
    *)
    默认分支
    ;;
esac
    
#case支持*,?,|,[]等通配符

3.2循环

3.2.1循环for
#方式1
for 变量名 in 列表;do
    循环体;
done
    
#方式2
for 变量名 in 列表
do
	循环体;
done
    
#双小括号(())
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
    循环体;
done
3.2.2循环while
#格式
while 判断条件  #判断条件为真进入循环体
do
    循环体;
done
    
#while read,依次读取文件的每一行,并赋值给line
while read line
do
    循环体;
done < 文件路径
3.2.3循环until
#格式
until 判断条件 #判断条件为假进入循环体
do
    循环体;
done
3.2.4循环控制语句continue

continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断,最内层为第1层

3.2.5循环控制语句break

break [N]:提前结束第N层整个循环,最内层为第1层

3.2.6循环控制shift命令

shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。

参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。

while 循环遍历位置参量列表时,常用到shift

3.2.7循环与菜单select
#格式
select NAME in list
do
    循环体;
done
  • select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准输出上,并显示 PS3 提示符,等待用户输入

  • 用户输入菜单列表中的某个数字,执行相应的命令

  • 用户输入菜单列表中的某个数字,会将对应的WORD值赋值给NAME变量

  • 用户输入被保存在内置变量 REPLY 中

  • select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环

  • select 经常和 case 联合使用

  • 与 for 循环类似,可以省略 in list,此时使用位置参量

4.函数function

4.1管理函数

函数是由函数名和函数体两部分组成的

4.1.1定义函数
#语法1:
func_name(){
    函数体;
}

#语法2:
function func_name(){
    函数何醒;
}

#语法3:
function func_name{
    函数体;
}
4.1.2查看函数
#查看当前已定义的函数名
declare -F
#查看当前已定义的函数定义
declare -f
#查看指定当前已定义的函数名
declare -f func_name
#查看当前已定义的函数名定义
declare -F func_name
4.1.3删除函数
unset func_name

4.2函数调用

函数只有被调用才会执行,通过给定函数名调用函数,函数名出现的地方,会被自动替换为函数代码,函数的生命周期为被调用时创建,返回时终止

函数的调用方式

  • 可在交互式环境下定义函数

  • 可将函数放在脚本文件中作为它的一部分

  • 可放在只包含函数的单独文件中

4.2.1交互式环境调用函数
4.2.2在脚本中定义及调用函数

函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用,调用函数仅使用其函数名即可

4.2.3使用函数文件

可以将经常使用的函数存入一个单独的函数文件,然后将函数文件载入shell,再进行调用函数。

函数文件载入shell,就可以在命令行或脚本中调用函数。

若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件

实现函数文件的过程:

  • 创建函数文件,只存放函数的定义

  • 在shell脚本或交互式shell中加载函数文件

  • 调用函数

#函数文件载入shell的方式
#方式1
$ . functions      #functions为函数文件的名称

#方式2
$ source functions

4.3函数的返回值return

函数默认返回值是函数体中最后一条命令的退出状态码;也可以使用return 自定义函数的返回值,在函数中使用 return,return 之后的语句将不会被执行。

return的用法:

  • return---->返回值:由return 语句的前一行命令执行结果决定

  • return 0----->返回值:无错误返回

  • return 1-255----->返回值:有错误返回

return和exit的区别:return只会中断函数的执行,而exit会中止整个shell脚本的执行

4.4环境函数

类似于环境变量,也可以定义环境函数,使子进程也可使用父进程定义的函数

#定义环境函数
export -f 函数名
declare -xf 函数名
    
#查看环境函数
export -f
declare -xf

4.5函数参数

传递参数给函数,在函数名后面以空白分隔给定参数列表即可,如:testfunc arg1 arg2 ...

在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $#等特殊变量

4.6函数变量

普通变量:只在当前shell进程中有效,函数外定义,可以在函数内修改

环境变量:当前shell和子shell有效

本地变量:作用域在函数内,函数结束会被自动销毁,且只能在函数内定义,在函数外定义会报错

#在函数内部定义本地变量
local NAME=VALUE

5.脚本相关工具

5.1信号捕捉trap

trap 命令可以捕捉信号,修改信号原来的功能,实现自定义功能。在脚本或程序的执行过程中,我们可以通过发送信号的方式,打断或终止程序的执行过程,为了避免这种情况,我们可以使用信号捕捉,来自定义信号处理。

#trap的使用
trap -l						#显示所有信号
trap -p						#显示所有自定义的信号
trap 'command' signal 		#自定义指定信号的处理方式
trap '' signal 				#忽略指定的信号
trap '-' signal 			#恢复信号默认操作
trap func EXIT 				#退出时执行func
    
#信号的三种表示方法:3) SIGQUIT
3 				#信号ID
SIGQUIT 		#完整写法,大小写都支持
QUIT 			#简短写法,大小写都支持

5.2创建临时文件mktemp

#常用选项
-d|--directory 				#创建目录
-u|--dry-run 				#只输出命令,不执行
-p DIR|--tmpdir[=DIR] 		#指明临时文件所存放目录位置
-t 							#将文件保存到$TMPDIR 定义的目录中,如果该变量未定义,则保存到/tmp 目录中

5.3安装复制文件install

#install 功能相当于cp,chmod,chown,chgrp ,mkdir 等相关工具的集合
#常用选项
-m|--mode=MODE 			#指定权限,默认755
-v|--verbose 			#显示过程
-o|--owner=OWNER 		#指定属主
-g|--group=GROUP 		#指定属组
-d|--directory DIR 		#指定目录,如果不存在就创建

6.数组

变量是存储单个元素的内存空间,数组是存储多个元素的连续的内存空间,相当于多个变量的集合。数组索引的编号从0开始,属于数值索引,但索引也可支持使用自定义的格式,而不仅是数值格式,即为关联索引,同时,bash 4.0版本之后开始支持bash的数组支持稀疏格式(索引不连续)

6.1声明数组

#普通数组和关联数组是不可以进行相互转换的

#普通数组可以不事先声明,直接使用
declare -a ARRAY_NAME
    
#关联数组必须先声明,再使用
declare -A ARRAY_NAME

6.2数组赋值

#一次只赋值一个元素
ARRAY_NAME[INDEX]=VALUE
    
#一次赋值全部元素
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
    
#只赋值特定元素
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
    
#交互式数组赋值
read -a ARRAY

6.3显示所有数组

declare -a

6.4引用数组

#引用数组中特定的元素
#如果省略[INDEX]表示引用下标为0的元素
${ARRAY_NAME[INDEX]}

#引用数组所有元素
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}

#数组的长度
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
    
#数组的所有下标
${!ARRAY_NAME[*]}
${!ARRAY_NAME[@]}

6.5删除数组

#删除数组中的元素
unset ARRAY[INDEX]
    
#删除整个数组
unset ARRAY

6.6数组数据处理

#从下标为offset开始(包含),取数组后面的number个元素
${ARRAY[@]:offset:number}
${ARRAY[*]:offset:number}

#从下标为offset开始(包含),取数组后面所有的元素
{ARRAY[@]:offset}
{ARRAY[*]:offset}

#取数组最前面的number个元素
${ARRAY[*]::number}

#向数组中追加元素
ARRAY[${#ARRAY[*]}]=value
ARRAY[${#ARRAY[@]}]=value

6.7关联数组

关联数组与普通数组区别:

  • 关联数组要先声明,才能使用,普通数组可以不用声明

  • 关联数组可以自定义下标,普通数组必须用数字

#声明关联数组,并赋值
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)

7.字符串处理

7.1字符串切片

#基于偏移量取字符串
#返回字符串变量var的字符的长度,一个汉字算一个字符
${#var}
    
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分
${var:offset}
    
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
${var:offset:number}
    
#取字符串的最右侧几个字符, 注意:冒号后必须有一空白字符
${var: -length}
    
#从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容,即:掐头去尾
${var:offset:-length}
    
#先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset
${var: -length:-offset}
    
    
#基于模式取子串
#从var变量的值中删除以word开头的部分
${var#word}
    
#其中word可以是指定的任意字符,自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删左留右
${var#*word}
    
#删除的是字符串开头至最后一次由word指定的字符之间的所有内容,即贪婪模式,以最后一个word为界删左留右
${var##*word}
${var##word}
    
#其中word可以是指定的任意字符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word,删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以从右向左的第一个word为界删右留左
${var%word*}
${var%word}
  
#同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符,即贪婪模式,以从右向左的最后一个word为界删右留左
${var%%word*}
${var%%word}

7.2查找替换

#查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之,懒惰模式
${var/pattern/substr}

#查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之,贪婪模式
${var//pattern/substr}
    
#查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}
    
#查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}

7.3查找并删除

#删除var表示的字符串中第一次被pattern匹配到的字符串,懒惰模式
${var/pattern}

#删除var表示的字符串中所有被pattern匹配到的字符串,贪婪模式
${var//pattern}
    
#删除var表示的字符串中所有以pattern为行首匹配到的字符串
${var/#pattern}
    
#删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
${var/%pattern}

7.4字符大小写转换

#把var中的所有小写字母转换为大写
${var^^}

#把var中的所有大写字母转换为小写
${var,,}

7.5变量扩展

#扩展以所有prefix开头的变量
${!prefix*}
${!prefix@}

8.高级变量

8.1高级变量赋值

$str 为变量名,expr 为具体字符串,下面的组合可以省掉一些 if,else 的判断代码

变量配置方式                 ​​​​​str没有配置         ​​​​​​​        ​​​​​​​ str为空字符串                 ​​​​​​​  str己配置为非空字符串

var=${str-expr}               var=expr                        var=                                 var=$str

var=${str:-expr}              var=expr                        var=expr                          var=$str

var=${str+expr}              var=                               var=expr                          var=expr

var=${str:+expr}             var=                               var=                                 var=expr

var=${str=expr}              str=expr;var=expr          str不变; var=                   str不变; var=$str

var=${str:=expr}             str=expr; var=expr         str=expr; var=expr          str不变; var=$str

var=${str?expr}             expr 输出至 stderr          var=                                 var=$str

var=${str:?expr}            expr 输出至 stderr          expr输出至stderr             var=$str

8.2高级变量用法-有类型变量

Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的

8.3变量间接引用

eval命令:首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量,该命令对变量进行两次扫描

间接变量引用:如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为

 

#bash Shell提供了两种格式实现间接变量引用
#方法1
#变量赋值
eval tempvar=\$$variable1
#显示值
eval echo \$$variable1
eval echo '$'$variable1
echo $tmpvar
    
#方法2
#变量赋值
tempvar=${!variable1}
#显示值
echo ${!variable1}

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值