linux变量之eval命令 变量替换,赋值,引用,字符串切片,字符串查找替换,字符串查找删除,大小写转换, 重要环境变量
eval命令
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
示例1:
[root@sea ~]#: cmd=whoami
[root@sea ~]#: echo $cmd
whoami #无法将whoami 执行
[root@sea ~]#: eval $cmd
root #可以将whoami 转换为命令执行
示例2:
[root@sea ~]#: n=5
[root@sea ~]#: echo {0..$n}
{0..5} #无法二次执行
[root@sea ~]#: eval echo {0..$n}
0 1 2 3 4 5 #置换后再次执行
变量替换
变量替换 | 说明 |
---|---|
${var# 匹配规则 } |
头开始匹配(删除),最短的数据删除 |
${var##匹配规则 } |
从头开始匹配(删除),最长的数据删除 [贪婪匹配] |
${var % 匹配规则 } |
从尾开始匹配(删除),最短的数据删除 |
${var%% 匹配规则 } |
从尾开始匹配(删除),最长的数据删除 [贪婪匹配] |
${var / 旧字符串/新字符串 } |
替换变量内的旧字符串为新字符串,只替换第一个 |
${var // 旧字符串/新字符串 } |
替换变量内的旧字符串为新字符串,替换全部 |
${var/#旧字符串/新字符串} |
查找var所表示的字符串中,行首被旧字符串所匹配到的字符串,以新字符串替换 |
${var/%旧字符串/新字符串} |
查找var所表示的字符串中,行尾被旧字符串所匹配到的字符串,以新字符串替换 |
i="www.hanjy.cn"&& echo ${i#*.}
hanjy.cn #头开始匹配(删除),最短的数据删除
i="www.hanjy.cn"&& echo ${i##*.}
cn #从头开始匹配(删除),最长的数据删除
i="www.hanjy.cn"&& echo ${i%.*}
www.hanjy #从尾开始匹配(删除),最短的数据删除
i="www.hanjy.cn"&& echo ${i%%.*}
www # 从尾开始匹配(删除),最长的数据删除
i="www.hanjy.cn"&& echo ${i/w/W}
Www.hanjy.cn #替换变量内的旧字符串为新字符串,只替换第一个
i="www.hanjy.cn"&& echo ${i//w/W}
WWW.hanjy.cn #替换变量内的旧字符串为新字符串,替换全部
i="www.www.hanjy.cn"&& echo ${i/#www/WWW}
WWW.www.hanjy.cn
i="www.hanjy.cn.cn"&& echo ${i/%cn/CN}
www.hanjy.cn.CN
变量赋值
变量赋值 | 说明 |
---|---|
${var=value} |
若var未设定,将值赋给变量var (空值或者非空值不处理) |
${var:=value} |
若未赋值或未设定的var,将值value值赋给它 (非空值不处理) |
${var-value} |
若未设定的var,将值value值赋给它,但value值不存储到var对应的地址空间 (非空值或者空值时不作处理) |
${var:-value} |
若未赋值或未设定的var,将值value值赋给它,但value值不存储到var对应的地址空间 (非空值时不作处理) |
${var+value} |
若var为空值或者非空值,重设其值 (没设定时不处理) |
${var:+value} |
若var为非空值,重设其值 (没设定或空值时不处理 ) |
${var?value} |
若var未设定,显示系统错误信息 ${var:?value} 会将value输出到标准错误 STDERR (空值或者非空值不处理) |
${var:?value} |
若var未设定或者空值,显示系统错误信息 ${var:?value} 会将value输出到标准错误STDERR (非空值不处理) |
```shell | 示例 |
#var={str-value} 当str不为空字符串时 将值赋给变量var
var={i-hello}&&echo var,i
hello,
#当str为空字符串时 变量var亦为空
i=""&&var=${i-hello}&&echo var,i
,
#当str为有值时 变量var=i
i="world"&&var={i-hello}&&echo var,i
world,world
#${var+value} 对已赋值的var,重设其值
i=“www.hanjy.cn”&& echo ${i+hello}
hello
#{var?value}和{var:?value} 对未赋值的var,显示系统错误信息
i=“www.hanjy.cn”&& echo ${tt:?}
-bash: tt: 参数为空或未设置
i=“www.hanjy.cn”&& echo ${tt?}
-bash: tt: 参数为空或未设置
i=“www.hanjy.cn”&& echo ${tt?error}
-bash: tt: error
i=“www.hanjy.cn”&& echo ${tt:?error}
-bash: tt: error
${var:=value} 对未赋值的var,将值value值赋给它 已赋值的输出结果
i=“www.hanjy.cn”&& echo ${ii:=hello}
hello
i=“www.hanjy.cn”&& echo ${i:=hello}
www.hanjy.cn
#${var:-value} 对未赋值的var,将值value值赋给它,但value值不存储到var对应的地址空间
i=“www.hanjy.cn”&& echo ${ii:-hello}
hello
### 字符串切片
`${#var}`:返回字符串变量var的长度
```shell|示例
i=hello && echo ${#i}
5
${var:offset}
:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到${#var}-1
之间(bash4.2后,允许为负值)
[root@sea ~]#: i=hello && echo ${i:1}
ello
${var:offset:number}
:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
i=hello && echo ${i:1:3}
ell
${var: -length}
:取字符串的最右侧几个字符 注意:冒号后必须有一空白字符
i=hello && echo ${i: -3}
llo
${var:offset: -length}
:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
i="hello world"&& echo ${i:2 : -3}
llo wo #左侧跳过两个字符(he) 取到最右侧前的3个字符(rld)前的内容
${var: -length:-offset}
:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容 注意:-length前空格
i="hello world"&& echo ${i: -5:2}
wo #先从后往前取5个字符(word) 在从前往后取2个字符
字符串查找并删除
查找删除 | 说明 |
---|---|
${var/pattern} : |
删除var表示的字符串中第一次被pattern匹配到的字符串 |
${var/pattern} : |
删除var表示的字符串中第一次被pattern匹配到的字符串 |
${var//pattern} : |
删除var表示的字符串中所有被pattern匹配到的字符串 |
${var/#pattern} : |
删除var表示的字符串中所有以pattern为行首匹配到的字符串 |
${var/%pattern} : |
删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串 |
#${var/pattern}:删除var表示的字符串中第一次被pattern匹配到的字符串
i="www.hanjy.cn"&& echo ${i/www.}
hanjy.cn
#${var//pattern}:删除var表示的字符串中所有被pattern匹配到的字符串
i="www.www.hanjy.cn"&& echo ${i//www. }
hanjy.cn
#${var/#pattern}:删除var表示的字符串中所有以pattern为行首匹配到的字符串
i="www.www.hanjy.cn"&& echo ${i/#www.}
www.hanjy.cn
#${var/%pattern}:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
i="www.hanjy.cn.cn"&& echo ${i/%.cn}
www.hanjy.cn
字符大小写转换
大小写转换 | 说明 |
---|---|
${var^^} |
把var中的所有小写字母转换为大写 |
${var,,} |
把var中的所有大写字母转换为小写 |
#${var^^}:把var中的所有小写字母转换为大写
i="www.hanjy.cn"&& echo ${i^^}
WWW.HANJY.CN
#${var,,}:把var中的所有大写字母转换为小写
i="WWW.HANJY.CN"&& echo ${i,,}
www.hanjy.cn
间接变量引用
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
var的值是var2,而var2又是变量名,var2的值为value,间接变量引用是指通过var1获得变量值value的行为
例如:
var1=var2
var2=value
#bash Shell提供了两种格式实现间接变量引用
#方式1: eval var=\$$var1;
var1=var2;var2=value;eval var=\$$var1;echo $var
value
#方式2: var=${!var1}
var1=var2;var2=value;var=${!var1};echo $var
value
环境变量文件
在shell的命令行下直接定义的变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,需要使用的话还需要重新定义。
如果只是临时用一下,可以直接在shell下用export命令设定环境变量;如果希望此环境变量每次开机或打开Shell时自动设定而无须每次都手动设定,那么需要将export命令写入环境变量配置文件中。Linux下,环境变量被分别保存在多个环境变量文件中,当你进入系统的时候,这些环境变量文件是按照下面的顺序读取的:
(1)/etc/environment文件
设置整个系统的环境信息,在系统启动时被读取,与登录用户无关。
(2)/etc/profile文件
为系统的每个用户设置环境信息,任何用户每次登录时执行该文件。
(3)/etc/bashrc文件
是针对所有用户的bash Shell初始化文件,任何用户每次登录或打开新的Shell时执行该文件。在执行完/etc/profile 内容之后,如果用户的Shell运行的是bash shell,那么接着就会执行此文件。
(4) ~/.bashrc文件
该文件包含专用于你的bash shell的bash信息,在用户每次登录时或打开新的Shell时执行该文件。
(5)~/.bash_profile文件
每个用户都可使用该文件保存专用于自己使用的shell信息,在用户每次登录时执行该文件。
注意:在不同Linux中,这个文件的名字不同,可能的名字有~/.bash_profile、~/.bash_login、~/.profile其中的一种或者几种。如果都存在的话,执行的顺序为~/.bash_profile、~/.bash_login、~/.profile。
(6) ~/.bash_logout文件
在用户每次退出登录的时候执行该文件。
/etc/environment文件、/etc/profile文件、/etc/bashrc文件是针对所有用户的。
/.bashrc文件、/.bash_profile文件、~/bash_logout文件在每个用户的主目录(HOME目录)下都存在,是针对特定用户的(哪个用户的主目录就针对哪个用户)。
例如,编辑/etc/profile文件,添加CLASSPATH变量:
vim /etc/profile
#添加内容如下:
export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib
注:修改文件后要想马上生效还要运行#source /etc/profile,不然只能在下次重进此用户时生效。
重要的环境变量
(1) BASH 和SHELL
BASH记录了bash Shell的路径,通常为/bin/bash,内部变量SHELL就是通过BASH的值确定当前Shell的类型。
SHELL变量保存默认的Shell值,默认的值为/bin/bash,表示当前的Shell是bash Shell。如果有必要用另一个Shell,则需要重置SHELL变量值。
下面显示了BASH和SHELL变量的值,由于Red Hat使用的是bash Shell,因而两个变量的值都是/bin/bash。
[root@localhost ~]# echo $BASH
/bin/bash
[root@localhost ~]# echo $SHELL
/bin/bash
(2) BASH_VERSION和BASH_VERSINFO[n]
BASH_VERSION表示安装在系统上的Bash版本号。
BASH_VERSINFO[n]是一个含有6个元素的数组, 它包含了所安装的Bash的版本信息,与下$BASH_VERSION很相像。
(3) SHLVL
SHLVL记录了bash Shell嵌套的层次,一般来说,我们启动第一个Shell时,SHLVL为1,如果在这个Shell中执行脚本,脚本中的SHLVL为2,如果脚本再执行子脚本,子脚本中的SHLVL就变为3。
(4)HOSTTYPE、MACHTYPE、OSTYPE
HOSTTYPE和MACHTYPE一样,都用于记录系统的硬件架构。
OSTYPE记录了操作系统类型。
(5) PATH
PATH是Linux中一个极为重要的环境变量,它用于帮助Shell找到用户所输入的命令。用户所输入的每个命令实际是是一个源代码文件,计算机执行这个文件里的代码以实现这个命令的功能,这些源代码文件称为可执行文件。可执行文件存在于各种各样的目录下,一些可执行文件放置在Linux系统标准目录中,还有一些可执行文件可能是用户写得的序或Shell脚本文件,他们放置在用户目录中。PATH就记录了一系列的目录列表,Shell为每个输入命令搜索PATH中的目录列表。
下面显示了PATH环境变量的内容,可以看到,PATH中包含了多个目录的路径,它们之间用冒号分割,都是以bin或sbin的文件夹结尾,bin或sbin是Linux中存放可执行文件的文件夹。任何在PATH的可执行文件都可以在Linux系统的任何目录中直接执行。
[root@hanjy ~]# echo $PATH
/usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
如果需要在PATH中添加新目录,可以使用以下的命令:
export PATH="/new directory":$PATH
命令中的new directory就是新加上去的目录,后面用冒号加$PATH,表示new directory加上旧的PATH变量值,得到新的PATH变量值。
(6)HOME
HOME记录当前用户的根目录。root用户的根目录时/root,其他用户的根目录都存放在/home目录下,通常以用户名命名。
(7)PWD和OLDPWD
PWD记录当前的目录路径,当利用cd命令改变当前目录时,系统自动更新PWD的值,OLDPWD记录旧的工作目录,即用户所处的前一个目录。
(8)USER、UID、LOGNAME
USER、UID、LOGNAME是保存用户信息的环境变量,USER表示当前登录用户的账户,UID表示当前登录用户的ID、LOGNAME表示当前登录用户的登录名。
(9)PPID
PPID是创建当前进程的进程号,即当前进程的父进程。
(10)PS1、PS2、PS3、PS4
PS1:主提示符,在命令行中可以见到它。默认显示“[\u@\h\W]$”。
PS2:第二提示符,当你需要额外输入的时候,你就会看到他。默认显示“>”。当命令比较长,需要多行输入时,在当行命令的末尾输入字符“\”,会出现下一行命令输入行,这时的提示符为第二提示符。
PS3:第三提示符,它在select循环中显示。默认显示“#?”。
PS4:第四提示符,当使用set -x选项来设置Shell的执行方式时,这个提示符会出现在每行输出的开头。默认显示“+”。
PS1、PS2、PS3、PS4是在用户根目录下的.bash_profile中定义的。可以更改这些提示符的显示样式。
下面列出了提示符中特殊字符的意义:
\d:代表日期,格式为weekday month date,例如:“Mon Aug 1”
\H:完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
\h:仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
\t:显示时间为24小时格式,如:HH:MM:SS
\T:显示时间为12小时格式
\A:显示时间为24小时格式:HH:MM
\u:当前用户的账号名称
\v:BASH的版本信息
\w:完整的工作目录名称。家目录会以~代替
\W:利用basename取得工作目录名称,所以只会列出最后一个目录
#:下达的第几个命令
$:提示字符,如果是root时,提示符为:# ,普通用户则为:$
(11)IFS
IFS用于指定Shell域分隔符,默认为空格。这个变量用来觉得Bash在解释字符串时如何识别域,或者单词边界。
data="windows, linux,MAC,Android"
#我们可以使用IFS读取变量中的每一个条目。
IFS=,
#IFS现在被设置为,
for i in $data;
do
echo DATA: $i
done
输出如下:
DATA: windows
DATA: linux
DATA: ,MAC
DATA: Android
注意,脚本内部修改IFS只在脚本内部起作用,当前Shell修改IFS只在当前Shell及子Shell中有效。
(12)MAIL
MAIL表示当前用户的邮件存放目录。
(13)HOSTNAME
HOSTNAME记录了主机名,Linux主机名是网络配置时必须要设置的参数,我们一般在/etc/sysconfig/network文件中设置主机名。/etc/hosts文件用于设定IP地址和主机名之间的对应关系,以利于快速从主机名查找到IP地址。
(14) LANG
系统字符集。
(15) SECONDS
SECONDS记录脚本从开始执行到结束所耗费的时间,以秒为单位。
(16)TMOUT
TMOUT变量用于设置Shell的过期时间,当TMOUT不为0时,Shell在TMOUT秒后将自动注销。TMOUT放在脚本中,可以规定脚本的执行时间。
(17) REPLY
REPLY变量与read和select命令有关。
read命令用于读取标准输入的变量值。在此,可以将read命令简单理解为接受用户的键盘输入,交互式Shell脚本经常用到read命令。read命令其一般格式为:
read variable
variable是变量名,read将读到的标准输入存储到variable变量中,read命令也可以不带任何变量名,此时,read就将读到的标准输入存储到REPLY变量中。新建脚本readreply.sh,内容如下:
readreply.sh脚本
#!/bin/bash
echo -n "What is your name?"
read
echo "Your name is $REPLY"
echo -n "What is the name of your father?"
read fname
echo "Your father's name is $fname"
readreply.sh脚本的执行结果如下:
[root@bogon ~]# . readreply.sh
What is your name?lcb
Your name is lcb
What is the name of your father?lqq
Your father's name is lqq
bash Shell的select命令源自于Korn Shell,是一种建立菜单的工具,它提供一组字符串供用户选择,用户不必完整地输入字符串,只需输入相应的序号进行选择,select命令的格式如下:
select variable in list
do
Shell命令1
Shell命令2
Shell命令3
......
break
done
上述select命令格式中的list是字符串列表,select自动将list形成有编号的菜单,用户输入序号以后,将该序号所对应的list中的字符串赋给variable变量,而序号值则保存到REPLY变量中。select命令的dobreak语句段中可以添加Shell命令,对variable或REPLY进行调用。
下例阐述select命令的用法,以及REPLY变量在select命令中的含义。新建一个名为selectreply.sh的脚本,内容如下:
#!/bin/bash
echo "Pls. choose your profession?"
select var in "Worker" "Doctor" "Teacher" "Student" "Other"
do
echo "The \$REPLY is $REPLY."
echo "Your profession is $var."
break
done
执行结果如下:
[root@bogon ~]# . selectreply.sh
Pls. choose your profession?
1) Worker
2) Doctor
3) Teacher
4) Student
5) Other
#? 4
The $REPLY is 4.
Your proffession is Student.
在上述selectreply.sh脚本的执行结果中,我们注意到输入select命令后,Shell提示符变为"#?",该提示符由Shell提示符变量PS3进行设置,“#?”是其默认值,可以重新设置。