侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Shell编程之特殊变量和扩展变量详解

技术  /  管理员 发布于 7年前   157

特殊变量

在Shell中的特殊变量主要分别两种位置参数变量、状态变量两种。

位置参数变量

Shell中的位置参数变量主要是指0、0、1、$#等,主要用于从命令行、函数或脚本执行等地方传递参数。详细说明如下所示:

  • $0:获取当前执行的Shell脚本的文件名,如脚本中包含路径,则输出也包括路径
  • $n:获取当前执行的Shell脚本的第n个参数值,如n>9,则需要使用用大括号,如${10},各参数间用空格进行分隔
  • $#:获取当前执行的Shell脚本传入参数的总个数
  • $*:获取当前执行的Shell所有传入参数,如不加引号则与$@功能相同,如果添加双引号**"∗",则表示将所有传入参数视为单个字符串∗∗,相当于"∗",则表示将所有传入参数视为单个字符串∗∗,相当于"1 223"
  • $@:获取当前执行的Shell所有传入参数,**如不加引号则与$*功能相同,如果添加双引号"@",则表示将所有传入参数视为独立的字符串∗∗,相当于"@",则表示将所有传入参数视为独立的字符串∗∗,相当于"1" "2""2""3"

当"∗"和"∗"和"@"都添加双引号时,两者的功能有所区别;如不加,则功能相同,无区别。

位置参数变量示例

1、示例一:

[root@localhost Test]# cat para.sh#!/bin/bashecho $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}echo '$0 is:' $0echo '$1 is:' $1echo '$12 is:' ${12}echo '$# is:' $#echo '$* is:' $*echo '"$*"is:' "$*"echo '$@ is:' $@echo '"$@"is:' "$@"# 输出结果[root@localhost Test]# bash ~/Test/para.sh {a..z}a b c d e f g h i j k l m n o$0 is: /root/Test/para.sh$1 is: a$12 is: l$# is: 26$* is: a b c d e f g h i j k l m n o p q r s t u v w x y z"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z$@ is: a b c d e f g h i j k l m n o p q r s t u v w x y z"$@"is: a b c d e f g h i j k l m n o p q r s t u v w x y z

1、传入的参数个数多于脚本定义的参数时,则多出的参数会忽略

2、传入的参数中如使用双引号,则会当作一个参数值进行传递

3、位置参数如大于9,需要使用${}进行传递

2、示例二:

[root@localhost Test]# cat testposition.sh #!/bin/bashecho '$# $1 $2 $3 $* $@'echo $# $1 $2 $3 $* $@echo "************"echo '$*'for tmp in $* do echo $tmp doneecho "************"echo "@@@@@@@@@@@@"echo '$@'for temp in $@ do echo $temp doneecho "@@@@@@@@@@@@"echo '"*"*"*"*"*"*'echo '$*'for i in "$*" do echo $i doneecho '"*"*"*"*"*"*'echo '"@"@"@"@"@"@'echo '$@'for j in "$@" do echo $j doneecho '"@"@"@"@"@"@'[root@localhost Test]# bash testposition.sh "Hello Jack" Welcome "to Shanghai"$# $1 $2 $3 $* $@3 Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai************$* # 未加双引号,所以会输出全部参数,则第一个和第三个参数会拆开HelloJackWelcometoShanghai************@@@@@@@@@@@@$@ # 未加双引号,所以会输出全部参数,则第一个和第三个参数会拆开HelloJackWelcometoShanghai@@@@@@@@@@@@"*"*"*"*"*"*$* # 添加双引号后,传入的参数全部当一个参数进行输出Hello Jack Welcome to Shanghai"*"*"*"*"*"*"@"@"@"@"@"@$@ # 添加双引号后,传入的参数全部当独立的参数进行输出Hello JackWelcometo Shanghai"@"@"@"@"@"@

状态变量

  • $?:获取上一个命令或脚本的执行状态值(0:成功,其他:失败)
  • $$:获取当前执行的Shell的进程号(PID)
  • $!:获取上一个在后台工作的进程的进程号
  • **$_**:获取在些之前执行的命令或脚本的最后一个参数

以上四个状态变量,仅$?常用,其他三个了解即可。

在日常使场景中,$?主要用法如下所示:

1、判断命令和脚本是否执行成功

2、如脚本中调用exit 数字,则会返回该数字给$?

3、如在函数中,则可以通过return 数字将该数字返回给$?

状态变量示例

1、$?示例:

[root@localhost Test]# ll /etc/profile-rw-r--r--. 1 root root 1819 4月 11 2018 /etc/profile[root@localhost Test]# echo $?0[root@localhost Test]# ll /etc/profildls: 无法访问/etc/profild: 没有那个文件或目录[root@localhost Test]# echo $?2

2、$$示例:

[root@localhost Test]# cat testPID.sh#!/bin/bashecho $$ > /tmp/test.pidsleep 300[root@localhost Test]# bash testPID.sh & # 将当前脚本调用到后台执行[1] 1671[root@localhost Test]# ps -ef | grep testPID | grep -v greproot 1671 23706 0 16:37 pts/0 00:00:00 bash testPID.sh # 查询PID

3、!示例:!示例:!功能类似于$$,只不过是获取上一次执行脚本的PID

[root@localhost Test]# bash testPID.sh &[1] 24078[root@localhost Test]# echo $!24078 # 打印上一次在后台执行的进程号[root@localhost Test]# ps -ef | grep testPID | grep -v greproot 24078 23706 0 16:42 pts/0 00:00:00 bash testPID.sh

4、$_示例:

[root@localhost Test]# bash para.sh {a..z}a b c d e f g h i j k l m n o$0 is: para.sh$1 is: a$12 is: l$# is: 26$* is: a b c d e f g h i j k l m n o p q r s t u v w x y z"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z$@ is: a b c d e f g h i j k l m n o p q r s t u v w x y z"$@"is: a b c d e f g h i j k l m n o p q r s t u v w x y z[root@localhost Test]# echo $_z # 打印最后一个传入的参数值

Bash 内置变量

常用的内部命令有echo、eval、exec、export、read、shift、exit。

echo

主要用于打印信息,其命令格式如下所示:

echo [options] args

常用参数如下所示:

参数选项 说明
-n 不换行输出内容
-e 解析转义字符

echo常用转义字符如下:

转义字符 说明
\n 换行
\r 回车
\t Tab
\b 退格
\v 纵向制表符

eval

当Shell程序运行到eval语句时,将读入参数args,并将它们组合成一个新的命令而后执行。其命令格式如下所示:

eval args

exec

exec主要用于在不创建新的子进程的情况下,转而执行指定的命令,当指定命令执行完后,则终止该进程。其命令格式如下所示:

exec args

当使用exec打开文件后,read命令每次都会将文件指针移动到下一行进行读取,直至结束。因此常用来处理文件内容。

read

从标准输入读取变量或字符串等信息并传递给其他变量,其命令格式如下所示

read args

shift

对传入的位置参数依次向左移动一个位置,并使用位置参数$#减1,直至0为止。其命令格式如下所示:

shift postition args

shift如果不带参数,则默认左移1位

如传入的参数为112 3,如执行一次shift,则之前的3,如执行一次shift,则之前的3变成2,2,2变成1,1,1消失。

exit

常用于退出Shell,在日常使用过程中可使用exit num来自定义返回状态数。

Bash 内置变量示例

1、echo

[root@localhost Test]# echo "Test";echo "Dao"TestDao[root@localhost Test]# echo -n "Test";echo "Dao"TestDao[root@localhost Test]# echo -e "Test\tName\n Dao"Test Name Dao

2、eval

[root@localhost Test]# cat eval.sh#!/bin/bashecho "No eval"echo \$$#echo "Add eval"eval echo \$$#[root@localhost Test]# bash eval.sh a bNo eval$2 # 未添加evel时,$#为2,则输出$2Add evalb # 添加evel后,则重新对传入的参数进行解析,则输出传入的第2个参数

3、exec

[root@localhost Test]# exec lseval.sh para.sh ping.sh testPID.sh testposition.sh[admin@localhost ~]$ # 在执行exec后则终止当前Shell进程,因此从root用户退出到普通用户# 与read一起读取文件[root@localhost ~]# seq 5 > /tmp/rand.log[root@localhost ~]# cat /tmp/rand.log 12345[root@localhost Test]# cat exec.sh#!/bin/bashexec < /tmp/rand.logwhile read line do echo $line doneecho "Completed"[root@localhost Test]# bash exec.sh12345Completed

4、read

可以参考公众号中read命令一文

5、shift

[root@localhost Test]# cat shift.sh#!/bin/bashecho $1 $2 $3 $4 $5until [ -z $1 ]do echo $@ shift 1done[root@localhost Test]# bash shift.sh {1..5}1 2 3 4 51 2 3 4 52 3 4 53 4 54 55

变量扩展

变量扩展说明

Shell中变量扩展说明如下所示:

  • ${var}:返回${var}的内容
  • ${#var}:返回${var}的字符长度
  • ${var:offset}:返回${var}从位置offset之后开始提取字符至结束
  • ${var:offset:length}:返回${var}从offset之后,提取长度为length的字符
  • ${var#word}:返回从${var}开头开始删除最短匹配的word子符串
  • ${var##word}:返回从${var}开头开始删除最长匹配的word子符串
  • ${var%word}:返回从${var}结尾开始删除最短匹配的word子符串
  • ${var%%word}:返回从${var}结尾开始删除最长匹配的word子符串
  • ${var/oldstring/newstring}:使用newstring替换第一个匹配的字符oldstring
  • ${var//oldstring/newstring}:使用newstring替换所有匹配的字符oldstring
  • ${var:-word}:如果变量var的值为空或未赋值,则将word做为返回值,常用于防止变量为空或未定义而导致的异常
  • ${var:=word}:如果变量var的值为空或未赋值,则将word赋值给var并返回其值。
  • ${var:?word}:如果变量var的值为空或未赋值,则将word做为标准错误输出,否则则输出变量的值,常用于捕捉因变量未定义而导致的错误并退出程序
  • ${var:+word}:如果变量var的值为空或未赋值,则什么都不做,否则word字符将替换变量的值

其中${var:-word}、${var:=word}、${var:?word}、${var:+word}中的冒号也可以省略,则将变量为空或未赋值修改为未赋值,去掉了为空的检测, 即运算符仅检测变量是否未赋值

变量扩展示例

[root@localhost init.d]# var="This is test string"[root@localhost init.d]# echo $varThis is test string[root@localhost init.d]# echo ${var}This is test string[root@localhost init.d]# echo ${#var} # 统计字符长度19[root@localhost init.d]# echo ${var:5} # 从第5个位置开始截取字符is test string[root@localhost init.d]# echo ${var:5:2} # 从第5个位置开始截取2个字符is[root@localhost init.d]# echo ${var#This} # 从开头删除最短匹配的字符 isis test string[root@localhost init.d]# echo ${var##This} # 从开头删除最长匹配的字符 isis test string[root@localhost init.d]# echo ${var%g} # 从结尾删除最短匹配的字符 isThis is test strin[root@localhost init.d]# echo ${var%%g} # 从结尾删除最长匹配的字符 isThis is test strin[root@localhost init.d]# echo ${var/is/newis} # 替换第一个匹配的字符Thnewis is test string[root@localhost init.d]# echo ${var//is/newis} # 替换所有匹配到的字符Thnewis newis test string[root@localhost init.d]# echo $centos # 变量未定义[root@localhost init.d]# echo ${centos:-UNDEFINE} # 变量为空,返回UNDEFINEUNDEFINE[root@localhost init.d]# centos="CentOS"[root@localhost init.d]# echo ${centos:-UNDEFINE} # 变量已经定义,返回变量本身的值CentOS[root@localhost init.d]# unset centos # 取消变量值[root@localhost init.d]# echo $centos[root@localhost init.d]# result=${centos:=UNDEFINE}[root@localhost init.d]# echo $resultUNDEFINE[root@localhost init.d]# echo $centos # 变量值为空,则将UNDEFINE赋值给centosUNDEFINE[root@localhost init.d]# unset centos[root@localhost init.d]# echo ${centos:?can not find variable centos}-bash: centos: can not find variable centos # 变量值为空,输出自定义错误信息[root@localhost init.d]# centos="IS DEFINED"[root@localhost init.d]# echo ${centos:?can not find variable centos}IS DEFINED  #变量值已定义,则输出变量值[root@localhost init.d]# unset centos[root@localhost init.d]# echo ${centos:+do nothing} # 变量值为空,什么都不操作输出[root@localhost init.d]# centos="do"[root@localhost init.d]# echo ${centos:+do nothing} # 变量已赋值,则输出自定义的消息do nothing

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对AIDI的支持。


  • 上一条:
    使用shell脚本安装lnmp的方法步骤
    下一条:
    Shell编程之变量数值计算方法示例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 国外服务器实现api.openai.com反代nginx配置(0个评论)
    • 2024/4/28最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客