变量除了可以直接设置来修改原本的内容之外,有没有办法通过简单的动作来将变量的内容
进行微调呢? 举例来说,进行变量内容的删除、取代与替换等!是可以的!我们可以通过几
个简单的小步骤来进行变量内容的微调喔! 下面就来试试看!
  变量内容的删除与取代
变量的内容可以很简单的通过几个咚咚来进行删除喔!我们使用 PATH 这个变量的内容来做
测试好了。 请你依序进行下面的几个例子来玩玩,比较容易感受的到鸟哥在这里想要表达的
意义:

范例一:先让小写的 path 自订变量设置的与 PATH 内容相同
[dmtsai@study ~]$ path=${PATH}
[dmtsai@study ~]$ echo ${path}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
范例二:假设我不喜欢 local/bin,所以要将前 个目录删除掉,如何显示?
[dmtsai@study ~]$ echo ${path#/*local/bin:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

上面这个范例很有趣的!他的重点可以用下面这张表格来说明:

${variable#/*local/bin:}
上面的特殊字体部分是关键字!用在这种删除模式所必须存在的
${variable#/*local/bin:}
这就是原本的变量名称,以上面范例二来说,这里就填写 path 这个“变量名称”啦!
${variable#/*local/bin:}
这是重点!代表“从变量内容的最前面开始向右删除”,且仅删除最短的那个
${variable#/*local/bin:}
代表要被删除的部分,由于 # 代表由前面开始删除,所以这里便由开始的 / 写起。
需要注意的是,我们还可以通过万用字符 * 来取代 0 到无穷多个任意字符
以上面范例二的结果来看, path 这个变量被删除的内容如下所示:
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

  很有趣吧!这样了解了 # 的功能了吗?接下来让我们来看看下面的范例三!

范例三:我想要删除前面所有的目录,仅保留最后一个目录
[dmtsai@study ~]$ echo ${path#/*:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 由于一个 # 仅删除掉最短的那个,因此他删除的情况可以用下面的删除线来看:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[dmtsai@study ~]$ echo ${path##/*:}
/home/dmtsai/bin
# 嘿!多加了一个 # 变成 ## 之后,他变成“删除掉最长的那个数据”!亦即是:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

  非常有趣!不是吗?因为在 PATH 这个变量的内容中,每个目录都是以冒号“:”隔开的, 所以
要从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的数据!但是 PATH 中不止一个冒号
(:) 啊! 所以 # 与 ## 就分别代表:

:符合取代文字的最短的那一个;
:符合取代文字的最长的那一个
上面谈到的是“从前面开始删除变量内容”,那么如果想要“从后面向前删除变量内容”呢? 这个
时候就得使用百分比 (%) 符号了!来看看范例四怎么做吧!

范例四:我想要删除最后面那个目录,亦即从 : 到 bin 为止的字串
[dmtsai@study ~]$ echo ${path%:*bin}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin
# 注意啊!最后面一个目录不见去!
# 这个 % 符号代表由最后面开始向前删除!所以上面得到的结果其实是来自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
范例五:那如果我只想要保留第一个目录呢?
[dmtsai@study ~]$ echo ${path%%:*bin}
/usr/local/bin
# 同样的, %% 代表的则是最长的符合字串,所以结果其实是来自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

  由于我是想要由变量内容的后面向前面删除,而我这个变量内容最后面的结尾
是“/home/dmtsai/bin”, 所以你可以看到上面我删除的数据最终一定是“bin”,亦即是“:bin”那个
代表万用字符! 至于 % 与 %% 的意义其实与 # 及 ## 类似!这样理解否?
例题:假设你是 dmtsai ,那你的 MAIL 变量应该是 /var/spool/mail/dmtsai 。假设你只想要保
留最后面那个文件名 (dmtsai) , 前面的目录名称都不要了,如何利用 $MAIL 变量来达成?
答:题意其实是这样“/var/spool/mail/dmtsai”,亦即删除掉两条斜线间的所有数据(最长符
合) 。 这个时候你就可以这样做即可:

[dmtsai@study ~]$ echo ${MAIL##/*/}

  相反的,如果你只想要拿掉文件名,保留目录的名称,亦即是“/var/spool/mail/dmtsai” (最短
符合) 。但假设你并不知道结尾的字母为何,此时你可以利用万用字符来处理即可,如下所
示:

[dmtsai@study ~]$ echo ${MAIL%/*}

了解了删除功能后,接下来谈谈取代吧!继续玩玩范例六啰!

范例六:将 path 的变量内容内的 sbin 取代成大写 SBIN:
[dmtsai@study ~]$ echo ${path/sbin/SBIN}
/usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 这个部分就容易理解的多了!关键字在于那两个斜线,两斜线中间的是旧字串
# 后面的是新字串,所以结果就会出现如上述的特殊字体部分啰!
[dmtsai@study ~]$ echo ${path//sbin/SBIN}
/usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/SBIN:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 如果是两条斜线,那么就变成所有符合的内容都会被取代喔!

  我们将这部份作个总结说明一下:

变量的测试与内容替换
在某些时刻我们常常需要“判断”某个变量是否存在,若变量存在则使用既有的设置,若变量不
存在则给予一个常用的设置。 我们举下面的例子来说明好了,看看能不能较容易被你所理解
呢!

范例一:测试一下是否存在 username 这个变量,若不存在则给予 username 内容为 root
[dmtsai@study ~]$ echo ${username}
<==由于出现空白,所以 username 可能不存在,也可能是空字串
[dmtsai@study ~]$ username=${username-root}
[dmtsai@study ~]$ echo ${username}
root <==因为 username 没有设置,所以主动给予名为 root 的内容。
[dmtsai@study ~]$ username="vbird tsai" <==主动设置 username 的内容
[dmtsai@study ~]$ username=${username-root}
[dmtsai@study ~]$ echo ${username}
vbird tsai <==因为 username 已经设置了,所以使用旧有的设置而不以 root 取代

  在上面的范例中,重点在于减号“ - ”后面接的关键字!基本上你可以这样理解:

new_var=${old_var-content}
新的变量,主要用来取代旧变量。新旧变量名称其实常常是一样的
new_var=${old_var-content}
这是本范例中的关键字部分!必须要存在的哩!
new_var=${old_var-content}
旧的变量,被测试的项目!
new_var=${old_var-content}
变量的“内容”,在本范例中,这个部分是在“给予未设置变量的内容”

  不过这还是有点问题!因为 username 可能已经被设置为“空字串”了!果真如此的话,那你还
可以使用下面的范例来给予 username 的内容成为 root 喔!

范例二:若 username 未设置或为空字串,则将 username 内容设置为 root
[dmtsai@study ~]$ username=""
[dmtsai@study ~]$ username=${username-root}
[dmtsai@study ~]$ echo ${username}
<==因为 username 被设置为空字串了!所以当然还是保留为空字串!
[dmtsai@study ~]$ username=${username:-root}
[dmtsai@study ~]$ echo ${username}
root <==加上“ : ”后若变量内容为空或者是未设置,都能够以后面的内容替换!

  在大括号内有没有冒号“ : ”的差别是很大的!加上冒号后,被测试的变量未被设置或者是已被
设置为空字串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与设置!这样
可以了解了吗?除了这样的测试之外, 还有其他的测试方法喔!

Tips 下面的例子当中,那个 var 与 str 为变量,我们想要针对 str 是否有设置来决定 var 的值
喔! 一般来说, str: 代表“str 没设置或为空的字串时”;至于 str 则仅为“没有该变量”。

根据上面这张表,我们来进行几个范例的练习吧! ^_^!首先让我们来测试一下,如果旧变量
(str) 不存在时, 我们要给予新变量一个内容,若旧变量存在则新变量内容以旧变量来替
换,结果如下:

测试:先假设 str 不存在 (用 unset) ,然后测试一下减号 (-) 的用法:
[dmtsai@study ~]$ unset str; var=${str-newvar}
[dmtsai@study ~]$ echo "var=${var}, str=${str}"
var=newvar, str= <==因为 str 不存在,所以 var 为 newvar
测试:若 str 已存在,测试一下 var 会变怎样?:
[dmtsai@study ~]$ str="oldvar"; var=${str-newvar}
[dmtsai@study ~]$ echo "var=${var}, str=${str}"
var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容

  关于减号 (-) 其实上面我们谈过了!这里的测试只是要让你更加了解,这个减号的测试并不
会影响到旧变量的内容。 如果你想要将旧变量内容也一起替换掉的话,那么就使用等号
(=) 吧!

测试:先假设 str 不存在 (用 unset) ,然后测试一下等号 (=) 的用法:
[dmtsai@study ~]$ unset str; var=${str=newvar}
[dmtsai@study ~]$ echo "var=${var}, str=${str}"
var=newvar, str=newvar <==因为 str 不存在,所以 var/str 均为 newvar
测试:如果 str 已存在了,测试一下 var 会变怎样?
[dmtsai@study ~]$ str="oldvar"; var=${str=newvar}
[dmtsai@study ~]$ echo "var=${var}, str=${str}"
var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容

  那如果我只是想知道,如果旧变量不存在时,整个测试就告知我“有错误”,此时就能够使用问
号“ ? ”的帮忙啦! 下面这个测试练习一下先!

测试:若 str 不存在时,则 var 的测试结果直接显示 "无此变量"
[dmtsai@study ~]$ unset str; var=${str?无此变量}
-bash: str: 无此变量 <==因为 str 不存在,所以输出错误讯息
测试:若 str 存在时,则 var 的内容会与 str 相同!
[dmtsai@study ~]$ str="oldvar"; var=${str?novar}
[dmtsai@study ~]$ echo "var=${var}, str=${str}"
var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容

  基本上这种变量的测试也能够通过 shell script 内的 if...then... 来处理, 不过既然 bash 有提供
这么简单的方法来测试变量,那我们也可以多学一些嘛! 不过这种变量测试通常是在程序设
计当中比较容易出现

来源:鸟哥私房菜

最新文章

  1. ArcGIS Engine开发前基础知识(2)
  2. ZeroMQ接口函数之 :zmq_strerror - 获取ZMQ错误描述字符串
  3. link与import的区别
  4. LCT专题练习
  5. mac共享文件给win7用户
  6. tomcat 启动时参数设置说明
  7. 把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列。
  8. HDU 1029 Ignatius and the Princess IV DP
  9. hibernate设置mysql的timestamp默认值技巧
  10. openSUSE13.1安装Nodejs并更新到最新版
  11. MyEclipse快捷键全
  12. 必应地图api文档,微软必应地图web开发版详解,可以在国内使用国外地图
  13. 201521123035《Java程序设计》第十一周作业
  14. MinHook测试与分析(x86下 E8,E9,EB,CALL指令测试,且逆推测试微软热补丁)
  15. Git Workflow简介
  16. 属性动画之ValueAnimator
  17. Python 3 中的json模块使用
  18. 【redis】redis5.0的一些新特性
  19. Jupyter Notebook 的安装使用以及 tree 路径变更
  20. CodeForces - 777B Game of Credit Cards 贪心

热门文章

  1. Nginx的gzip
  2. Java当中的IO二
  3. Linux shell编程— 命令替换
  4. Update API
  5. 用Java实现给图片添加文字
  6. netsh winsock reset命令
  7. 封装nodeJS中 $on $emit $off 事件
  8. Python内置函数(40)——map
  9. css实现超出文本省略号的两个方法
  10. Unity 本地坐标到世界坐标,世界坐标到本地坐标