标签:shell特殊位置参数变量 内置变量使用 eval set
博主名: 李常明
博文地址: http://keep88.blog.51cto.com
此笔记出自老男孩书籍: 跟老男孩学linux运维 shell编程实战
shell变量知识进阶与实践
1、shell中的特殊位置参数变量:
| 位置变量 | 作用说明 |
| $0 | 获取当前执行的shell脚本的文件名,如果执行脚本包含了路径,会输出脚本路径 |
| $n | n=1..9 获取当前执行的shell脚本的第n个参数值,n为0时,输出脚本文件名,n>9 时,必须用大括号括起来,如${10} |
| $# | 获取当前执行的shell脚本后面接的参数的总个数 |
| $* | 获取当前shell脚本所有传参的参数,如果给$*加上双引号,例:"$*"则会将所有的参数视为单个字符串,如 "$1 $2 $3....." |
| $@ | 获取当前shell脚本所有传参的参数,如果给$@加上双引号,例:"$@"则会将所有的参数视为不同的独立字符串,如“$1” "$2" "$3" ... |
例如:
1)、$n的使用:n为{1..15}
小技巧:
[root@localhost test]# echo \${1..15}
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[root@localhost test]# echo \a{1..10}
a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 #>== 利用此技巧可以快速输出有规律的字符串
[root@localhost test]# pwd
/root/test
[root@localhost test]# vim t1.sh
[root@localhost test]# cat t1.sh
echo $1
[root@localhost test]# sh t1.sh test
test
[root@localhost test]# sh t1.sh zhangsan lisi
zhangsan
[root@localhost test]# vim t1.sh
[root@localhost test]# cat t1.sh
echo $1 $2 $3
[root@localhost test]# sh t1.sh zhangsan wangwu lisi
zhangsan wangwu lisi需注意:
当参数大于9时,必须用${10} ${11} ${12}.....${15} 使用大括号括起来
2)、$0的使用:
[root@localhost test]# vim t2.sh [root@localhost test]# cat t2.sh echo $0 [root@localhost test]# sh t2.sh t2.sh [root@localhost test]# sh t2.sh zhangsan t2.sh 注: 列举两个命令的使用 1)、dirname和basename dirname: 获取路径 basename:获取文件名 [root@localhost test]# dirname /root/test/t1.sh /root/test [root@localhost test]# basename /root/test/t1.sh t1.sh
3)、$#的使用:
[root@localhost test]# vim t2.sh [root@localhost test]# cat t2.sh echo $# [root@localhost test]# sh t2.sh zhangsan lisi wangwu test1 test2 5
4)、$* $@ "$*" "$@"的区别:
结合上述概念,举例分析这四个区别:
1)、使用set设置位置参数(同命令行脚本的传参) [root@localhost ~]# set -- "I am" smart boy. [root@localhost ~]# echo $# 3 [root@localhost ~]# echo $1 I am [root@localhost ~]# echo $2 smart [root@localhost ~]# echo $3 boy. 2)、测试$*和$@,没有带双引号 [root@localhost ~]# echo $* I am smart boy. [root@localhost ~]# echo $@ I am smart boy. 使用for循环输出所有参数: [root@localhost ~]# for i in $*;do echo $i;done I am smart boy. [root@localhost ~]# for i in $@;do echo $i;done I am smart boy. 3)、测试"$*" 和 "$@" ,注意使用了双引号 [root@localhost ~]# echo "$*" I am smart boy. [root@localhost ~]# echo "$@" I am smart boy. 使用for输出所有参数: [root@localhost ~]# for i in "$*";do echo $i;done I am smart boy. [root@localhost ~]# for i in "$@";do echo $i;done I am smart boy. 小结: 回顾开头我们写的概念分析: $*和$@不加引号,输出所有参数,在for语句中,如果有空格分隔的字符串,会拆分输出 $*和$@都加上引号,例"$*" "$@",此时区别: $* 会将所有参数,作为完整的字符串输出,如上所示 $@ 会将所有参数,作为独立的单个字符输出,如果有空格分隔的字符串,不会拆分输出,作为独立的单个字符输出. 注释: set 和eval命令的使用详解: set可以同命令行一样,可以传参 eval命令:首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时被称为复杂变量 例如: [root@localhost ~]# A="cat t1.sh" [root@localhost ~]# echo $A cat t1.sh [root@localhost ~]# eval $A #>== 此时eval命令对变量进行置换,还执行了其中的命令 I am smart boy. set与eval的使用,在编写脚本会用到的例子: 例1)、 [root@localhost ~]# Number=$(set -- $(cat t4.sh); eval "echo \$$#") 注释: set 设置传入的参数, eval进行两次扫描, $#:输出所有的位置参数总数, $$#:将总数,也就是最后一个位置参数的值,赋值给Number [root@localhost ~]# echo $Number 5 例2)、 [root@localhost ~]# runlevel N 5 [root@localhost ~]# Runlevel=$(set -- $(runlevel);eval "echo \$$#") [root@localhost ~]# echo $Runlevel 5
2、shell进程中的特殊状态变量:
$? 获取执行上一个指令的执行状态返回值(0为成功,非0表示失败)
3、bash Shell内置变量命令:
1)、echo参数
| echo参数选项 | 说明 |
| -n | 不换行输出内容 |
| -e | 解析转义字符 |
| 转移字符: | |
| \n | 换行 |
| \t | 制表符 |
| \r | 回车 |
| \b | 退格 |
| \v | 纵向制表符 |
2)、eval命令使用
[root@localhost ~]# cat t1.sh echo \$$# [root@localhost ~]# sh t1.sh arg1 arg2 $2 #>== $#:输出位置参数总数2 $$#:$2 echo输出$2
[root@localhost ~]# cat t1.sh eval echo \$$# #>== 加入eval命令,将echo $5 以命令输出结果 [root@localhost ~]# sh t1.sh arg1 arg2 arg3 arg4 arg4
3)、shift
shift命令的主要作用是将位置参数$1,$2等进行左移,即如果位置参数是$3,$2,$1, 那么执行一次shift后,$3 就变成了$2,$2就变成了$1,$1,就消失了。
例如:
[root@localhost ~]# cat t4.sh echo $1 $2 if [ $# -eq 2 ];then shift echo $1; fi [root@localhost ~]# sh t4.sh arg1 arg2 arg1 arg2 arg2 #>== 执行shift命令后,arg1 被左移掉了,剩下了新的$1,即arg2
4、Shell变量字串知识及实践
| 表达式 | 说明 |
| ${parameter} | 返回变量$parameter的内容 |
| ${#parameter} | 返回变量$parameter内容的长度 |
| ${parameter:offset} | 在变量${parameter}中,从位置offset之后开始提取字串到结尾 |
| ${parameter:offset:length} | 在变量${parameter}中,从位置offset之后开始提取长度为length的字串 |
| ${parameter#word} | 从变量${parameter}开头删除最短匹配的word字串 |
| ${parameter##word} | 从变量${parameter}开头删除最长匹配的word字串 |
| ${parameter%word} | 从变量${parameter}结尾开始删除最短匹配的word字串 |
| ${parameter%%word} | 从变量${parameter}结尾开始删除最长匹配的word字串 |
| ${parameter/pattern/string} | 使用string代替第一个匹配的pattern |
| ${parameter//pattern/string} | 使用string代替所有匹配的pattern |
举例说明各内置变量的使用:
1)、${#parameter} :计算长度
[root@localhost ~]# name="lichangming"
[root@localhost ~]# echo ${#name}
11 #>== 正好11个字符”lichangming“2)、${parameter:offset}: 指定位置之后提取内容到结尾,同python中的切片类似
[root@localhost ~]# name="lichangming"
[root@localhost ~]# echo ${name:3}
hangming
[root@localhost ~]# echo ${name:2}
changming3)、${parameter:offset:length} :从位置offset之后开始提取长度为length的字串
[root@localhost ~]# name="lichangming"
[root@localhost ~]# echo ${name:2:7}
changmi #>==输出第2个位置之后到第7个位置的内容注:
此上的截取内容方法,同cut -c命令的功能
例如:
[root@localhost ~]# echo $name
lichangming
[root@localhost ~]# echo ${name} | cut -c 2-7
ichang #>== cut命令,后接的数字表示:截取2~7个位置的字符
注意和内置变量的区别,内置变量的第一个offset,起始位置为offset之后的内容4)、${parameter#word} :从开头开始删除最短匹配word字串
[root@localhost ~]# echo $name
lichangming
[root@localhost ~]# echo ${name#l*g}
ming #>== 匹配了l至g范围的字串,将其删除,注意一定是从头开始匹配,最短匹配
[root@localhost ~]# echo ${name#c*g}
lichangming #>==c不是从开头匹配的,所以没有找到匹配项,未删除,输出所有5)、${parameter##word} :删除从头开始最长匹配
[root@localhost ~]# name="lichangmingcming"
[root@localhost ~]# echo $name
lichangmingcming
[root@localhost ~]# echo ${name##l*c}
ming #>== 最长匹配,匹配了lichangmingc,将其删除,剩下ming
看看最短匹配删除的结果:
[root@localhost ~]# echo ${name#l*c}
hangmingcming #>==最短匹配,匹配了lic,删除以上匹配删除,都是从头开始删除。
6)、${parameter%word}:从末尾删除最短匹配
7)、${parameter%%word}: 从末尾删除最长匹配
例如:
[root@localhost ~]# echo $name
lichangmingcming
[root@localhost ~]# echo ${name%i*g}
lichangmingcm
[root@localhost ~]# echo ${name%%i*g}
l
[root@localhost ~]# echo ${name%%c*m}
lichangmingcming
[root@localhost ~]# echo ${name%%m*g}
lichang注意:
从末尾匹配,指第一个值与末尾g 范围的字串,在上述例子中,c*m, 开头为c,中间为任意值,末尾为m,则未找到匹配结果,输出了所有,所以,一定谨记是第一个值与末尾匹配。
8)、${parameter/pattern/string} :将string替换第一匹配到的模式pattern
[root@localhost ~]# name="li2chang3ming4hehe8"
[root@localhost ~]# echo $name
li2chang3ming4hehe8
[root@localhost ~]# echo ${name/3*4/test}
li2changtesthehe89)、${parameter//pattern/string} :将string替换所有匹配到的模式pattern
[root@localhost ~]# name="zhangsan lisi wangwu zhangsan liming"
[root@localhost ~]# echo $name
zhangsan lisi wangwu zhangsan liming
[root@localhost ~]# echo ${name//zhangsan/someone}
someone lisi wangwu someone liming注:
使用以上的方法,批量修改文件名
1)、生成测试文件:
[root@localhost test]# pwd
/root/test
[root@localhost test]# ls
[root@localhost test]# touch \smart_t{1..9}.sh
[root@localhost test]# ls
smart_t1.sh smart_t3.sh smart_t5.sh smart_t7.sh smart_t9.sh
smart_t2.sh smart_t4.sh smart_t6.sh smart_t8.sh批量改名: 将smart_t*.sh改为silly_t*.sh
[root@localhost test]# ls
smart_t1.sh smart_t3.sh smart_t5.sh smart_t7.sh smart_t9.sh
smart_t2.sh smart_t4.sh smart_t6.sh smart_t8.sh
[root@localhost test]# for i in `ls *.sh`;do mv $i `echo ${i//smart/silly}`; done
[root@localhost test]# ls
silly_t1.sh silly_t3.sh silly_t5.sh silly_t7.sh silly_t9.sh
silly_t2.sh silly_t4.sh silly_t6.sh silly_t8.sh此方法为使用变量的字串替换 来实现的改名方法。
2)、使用rename命令改名:
[root@localhost test]# rename "smart" "silly" /root/test/*.sh [root@localhost test]# ls silly_t1.sh silly_t3.sh silly_t5.sh silly_t7.sh silly_t9.sh silly_t2.sh silly_t4.sh silly_t6.sh silly_t8.sh
3)、for循环结合sed实现批量改名:
[root@localhost test]# ls silly_t1.sh silly_t3.sh silly_t5.sh silly_t7.sh silly_t9.sh silly_t2.sh silly_t4.sh silly_t6.sh silly_t8.sh [root@localhost test]# for i in `ls *.sh`;do mv $i `echo $i | sed s/silly/smart/g`;done [root@localhost test]# ls smart_t1.sh smart_t3.sh smart_t5.sh smart_t7.sh smart_t9.sh smart_t2.sh smart_t4.sh smart_t6.sh smart_t8.sh
本文出自 “keep常明” 博客,请务必保留此出处http://keep88.blog.51cto.com/11829099/1930977
标签:shell特殊位置参数变量 内置变量使用 eval set
原文地址:http://keep88.blog.51cto.com/11829099/1930977