shell 变量使用利器

shell 变量替换 大全

处理或/并扩展变量

${parameter}

和$parameter是相同的,都是表示变量parameter的值。在一些环境中,使用${parameter}比较不会引起误解.

可以把变量和字符串连接.

your_id=${USER}-on-${HOSTNAME} 2 echo "$your_id" 3 # 4 echo "Old \$PATH = $PATH" 5 PATH=${PATH}:/opt/bin #在脚本的生存期内,能额外增加路径/opt/bin到环境变量$PATH中去. 6 echo "New \$PATH = $PATH"
${parameter-default},   ${parameter:-default}

如果变量没有被设置,使用默认值。

echo ${username-`whoami`} 2 # 如果变量$username还没有被设置,则把命令`whoami`的结果赋给该变量.
Note

${parameter-default}和${parameter:-default}几乎是相等的。它们之间的差别是:当一个参数已被声明,但是值是NULL的时候两者不同.

#!/bin/bash 2 # param-sub.sh 3  # 变量是否被声明, 5 #+ 即使它的值是空的(null) 6 #+ 也会影响是否使用默认值. 7  username0= 9 echo "username0 has been declared, but is set to null." 10 echo "username0 = ${username0-`whoami`}" 11 # 不会有输出. 12  13 echo 14  15 echo username1 has not been declared. 16 echo "username1 = ${username1-`whoami`}" 17 # 会输出默认值. 18  19 username2= 20 echo "username2 has been declared, but is set to null." 21 echo "username2 = ${username2:-`whoami`}" 22 # ^ 23 # 和上面一个实例比较. 24 # 有输出是因为:-比-多一个测试条件. 25  26  27 # 28  29 # 再来一次: 30  31 variable= 32 # 变量已声明,但被设置了空值(null). 33  34 echo "${variable-0}" # (没有输出) 35 echo "${variable:-1}" # 1 36 # ^ 37  38 unset variable 39  40 echo "${variable-2}" # 2 41 echo "${variable:-3}" # 3 42  43 exit 0

默认值结构可以在脚本中提供一个没有传递命令行参数时的默认值.

DEFAULT_FILENAME=generic.data 2 filename=${1:-$DEFAULT_FILENAME} 3 # 如果没有指定值,下面的代码会使用filename变量的默认值"generic.data". 4 # 5 # 6 # 其他的代码...

参考例子 3-4, 例子 28-2,和例子 A-6.

使用一个and list来提供一个默认的命令行参数作比较.

${parameter=default},   ${parameter:=default}

如果变量parameter没有设置,把它设置成默认值.

两种形式几乎相同,只是和上面的一样[1]:只有当$parameter变量被声明且被设置成null值时不同.

echo ${username=`whoami`} 2 # 变量"username"现在已经被设置成`whoami`的输出.
${parameter+alt_value},   ${parameter:+alt_value}

如果变量parameter设置,使用alt_value作为新值,否则使用空字符串。

除了引起的当变量被声明且值是空值时有些不同外,两种形式几乎相等。请看下面的例子.

echo "###### \${parameter+alt_value} ########" 2 echo 3  a=${param1+xyz} 5 echo "a = $a" # a = 6 param2= 8 a=${param2+xyz} 9 echo "a = $a" # a = xyz 10  11 param3=123 12 a=${param3+xyz} 13 echo "a = $a" # a = xyz 14  15 echo 16 echo "###### \${parameter:+alt_value} ########" 17 echo 18  19 a=${param4:+xyz} 20 echo "a = $a" # a = 21  22 param5= 23 a=${param5:+xyz} 24 echo "a = $a" # a = 25 # 产生与a=${param5+xyz}不同。 26  27 param6=123 28 a=${param6+xyz} 29 echo "a = $a" # a = xyz
${parameter?err_msg},   ${parameter:?err_msg}

如果变量parameter已经设置,则使用该值,否则打印err_msg错误信息。

这两种形式几乎相同,仅有和上面所说的一点不同:带有:使当变量已声明但值是空值时不同.


例子 9-14. 使用参数替换和错误信息

#!/bin/bash 2  # 检查一些系统环境变量 4 # 这是很好的预防性防护. 5 # 例如,如果$USER(用户在控制台的名字)没有被设置, 6 #+ 系统将不接受你. 7  : ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?} 9  echo 10  echo "Name of the machine is $HOSTNAME." 11  echo "You are $USER." 12  echo "Your home directory is $HOME." 13  echo "Your mail INBOX is located in $MAIL." 14  echo 15  echo "If you are reading this message," 16  echo "critical environmental variables have been set." 17  echo 18  echo 19  20 # ------------------------------------------------------ 21  22 # ${variablename?}结构也能检查一个脚本中变量的设置情况 23 # 24  25 ThisVariable=Value-of-ThisVariable 26 # 注意,顺便说一下字符串变量可能被设置成不允许的字符 27 # 28 : ${ThisVariable?} 29 echo "Value of ThisVariable is $ThisVariable". 30 echo 31 echo 32  33  34 : ${ZZXy23AB?"ZZXy23AB has not been set."} 35 # 如果变量ZZXy23AB没有被设置, 36 #+ 则脚本会打印一个错误信息而结束。 37  38 # 你可以指定错误信息. 39 # : ${variablename?"ERROR MESSAGE"} 40  41  42 # 等同于: dummy_variable=${ZZXy23AB?} 43 # dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."} 44 # 45 # echo ${ZZXy23AB?} >/dev/null 46  47 # 使用命令"set -u"后,再比较这些检查变量是否被设置的方法的不同... 48 # 49  50  51  52 echo "You will not see this message, because script already terminated." 53  54 HERE=0 55 exit $HERE # 不会执行到这儿. 56  57 # 实际上,这个脚本会返回退出状态码为1(echo $?).


例子 9-15. 变量替换和"usage"信息[译者注:通常就是帮助信息]

#!/bin/bash 2 # usage-message.sh 3  : ${1?"Usage: $0 ARGUMENT"} 5 # 如果没有提供命令行参数则脚本在这儿就退出了, 6 #+ 并打印了错误信息. 7 # usage-message.sh: 1: Usage: usage-message.sh ARGUMENT 8  echo "These two lines echo only if command-line parameter given." 10 echo "command line parameter = \"$1\"" 11  12 exit 0 # 仅在命令行参数提供时,才会在这儿退出. 13  14 # 分别检查有命令行参数和没有命令行参数时的退出状态。 15 # 如果有命令行参数,则"$?"为0. 16 # 否则, "$?"为1.

变量替换与/或扩展. 下面的各种表达式是expr字符串操作中match的补充(参考Example 12-9). 它们通常都用来解析文件路径名.

变量长度/子串提取

${#var}

字符串长度(即变量$var的字符个数)。对于数组来说,${#array}是数组的第一个元素的升序.

Note

例外情况:

  • ${#*}${#@} 表示位置参数的个数.

  • 对于一个数组来说,${#array[*]}${#array[@]}表示数组中元素的个数.


例子 9-16. 变量值的长度

#!/bin/bash 2 # length.sh 3  E_NO_ARGS=65 5  if [ $# -eq 0 ] # 必须要有命令行参数给这个演示程序. 7 then 8  echo "Please invoke this script with one or more command-line arguments." 9  exit $E_NO_ARGS 10 fi 11  12 var01=abcdEFGH28ij 13 echo "var01 = ${var01}" 14 echo "Length of var01 = ${#var01}" 15 # 现在,让我们在变量值内嵌入一个空格. 16 var02="abcd EFGH28ij" 17 echo "var02 = ${var02}" 18 echo "Length of var02 = ${#var02}" 19  20 echo "Number of command-line arguments passed to script = ${#@}" 21 echo "Number of command-line arguments passed to script = ${#*}" 22  23 exit 0

${var#Pattern},   ${var##Pattern}

删除从$var前端开始的最短或最长匹配$Pattern的字符串。

例子 A-7中的用法示例:

# 摘自"days-between.sh"例子的函数 2 # 剥去传递来的参数的前引0. 3  strip_leading_zero () # 剥去传递的参数中可能存在的前导0 5 { # 6  return=${1#0} # "1"表示变量"$1" -- 传给函数的参数. 7 } # 而"0"表示要从"$1"前端剥掉的字符 -- 剥掉0

Manfred Schwarb给出了比上面更多的细节的例子:

strip_leading_zero2 () # 剥除前导的0字符,因为不这样 2 { # Bash会把这串字符当成八进制值. 3  shopt -s extglob # 激活扩展匹配. 4  local val=${1##+(0)} # 使用局部变量,匹配最长的0. 5  shopt -u extglob # 禁用扩展匹配. 6  _strip_leading_zero2=${val:-0} 7  # 如果输入是0,返回0来替换返回"". 8 }

另外一个usage(帮助信息)示例:

echo `basename $PWD` # 当前工作目录的基本名字. 2 echo "${PWD##*/}" # 当前工作目录的基本名字. 3 echo 4 echo `basename $0` # 脚本名. 5 echo $0 # 脚本名. 6 echo "${0##*/}" # 脚本名. 7 echo 8 filename=test.data 9 echo "${filename##*.}" # data 10  # 文件的扩展名.
${var%Pattern},   ${var%%Pattern}

删除从$var前端开始的最短或最长匹配$Pattern的字符串。

Bash的 版本2增加了附加的选项。

例子 9-17. 在参数替换中的模式匹配

#!/bin/bash 2 # patt-matching.sh 3  # 使用# ## % %%的参数替换操作的模式匹配. 5  var1=abcd12345abc6789 7 pattern1=a*c # * (星号)匹配a - c的所有字符. 8  echo 10 echo "var1 = $var1" # abcd12345abc6789 11 echo "var1 = ${var1}" # abcd12345abc6789 12  # (另一种形式) 13 echo "Number of characters in ${var1} = ${#var1}" 14 echo 15 16 echo "pattern1 = $pattern1" # a*c (此表达式匹配'a'与'c'之间的所有字符) 17 echo "--------------" 18 echo '${var1#$pattern1} =' "${var1#$pattern1}" # d12345abc6789 19 # 匹配开头的最短字串                   abcd12345abc6789 20 # ^^^^^ |-| 21 echo '${var1##$pattern1} =' "${var1##$pattern1}" # 6789 22 # 最长匹配,剥掉开头的12个字符              abcd12345abc6789 23 # ^^^^^ |----------| 24  25 echo; echo; echo 26  27 pattern2=b*9 # 匹配'b'和'9'之间的所有字符 28 echo "var1 = $var1" # 仍然是 abcd12345abc6789 29 echo 30 echo "pattern2 = $pattern2" 31 echo "--------------" 32 echo '${var1%pattern2} =' "${var1%$pattern2}" # abcd12345a 33 # 最短匹配, 剥去后面的6个字符 abcd12345abc6789 34 # ^^^^ |----| 35 echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a 36 # 最长匹配, 剥去后面的12个字符              abcd12345abc6789 37 # ^^^^ |-------------| 38  39 # 记住, #和##表示在字符串的左边(即开头)操作, 40 # %和%%表示在字符串的右边(即结尾)操作. 41  42 echo 43  44 exit 0


例子 9-18. 更改文件扩展名(后缀):

#!/bin/bash 2 # rfe.sh: 更改文件扩展名. 3 # 4 # rfe old_extension new_extension 5 # 6 # 例如: 7 # T为了把当前目录下所有的*.gif文件改成*.jpg,如下执行: 8 # rfe gif jpg 9  10  11 E_BADARGS=65 12  13 case $# in 14  0|1) # 在这里,竖线(|)意味着"或"。 15  echo "Usage: `basename $0` old_file_suffix new_file_suffix" 16  exit $E_BADARGS # 如果是0或1,就退出脚本 17  ;; 18 esac 19  20  21 for filename in *.$1 22 # 把文件名以第一个参数为后缀的文件全部列举出来 23 do 24  mv $filename ${filename%$1}$2 25  # 剥去文件名中匹配第一个参数的部分, 26  #+ 然后加上第二个参数. 27 done 28  29 exit 0

变量扩展/子串替换

这些结构从ksh中学习而来.

${var:pos}

变量var被展开成从位移pos个字符往后的值.

${var:pos:len}

从变量var中展开成从位移pos的字符往后最长为len的字符串。参考例子 A-14中这个操作符的创造性用法。

${var/Pattern/Replacement}

在变量var第一个匹配Pattern的字符串用Replacement代替.

如果省略了Replacement ,则第一个匹配Pattern的字符串会被删除.

${var//Pattern/Replacement}

全局替换Global replacement.所有在变量var中被Pattern匹配到的都由Replacement代替.

和上面的一样,如果Replacement被省略,则所有的匹配Pattern的字符串都会被删除.


例子 9-19. 用模式匹配来解析任意的字符串

#!/bin/bash 2  var1=abcd-1234-defg 4 echo "var1 = $var1" 5  t=${var1#*-*} 7 echo "var1 (with everything, up to and including first - stripped out) = $t" 8 # t=${var1#*-} 也一样, 9 #+ 因为 # 匹配最短的字符串, 10 #+ 并且 * 匹配前面所说的所有字符,也包括空字符串. 11 # (多谢Stephane Chazelas指出这一点.) 12  13 t=${var1##*-*} 14 echo "If var1 contains a \"-\", returns empty string... var1 = $t" 15 16  17 t=${var1%*-*} 18 echo "var1 (with everything from the last - on stripped out) = $t" 19  20 echo 21  22 # ------------------------------------------- 23 path_name=/home/bozo/ideas/thoughts.for.today 24 # ------------------------------------------- 25 echo "path_name = $path_name" 26 t=${path_name##} 是更一般的解决办法, 30 #+ 但有时还是会失败. 31 # 如果$path_name 以一个新行符结尾,那么 `basename $path_name` 就不能正常工作了, 32 #+ 但上面的表达式可以正常工作. 33 # (多谢, S.C.) 34  35 t=${path_name%/*.*} 36 # 效果和 t=`dirname $path_name` 一样 37 echo "path_name, stripped of suffixes = $t" 38 # 有时这会失败,比如"../", "/foo", # "foo/", "/". 39 # 移除前缀,特别当basename没有前缀时, 40 #+ 但目录名可以,但也使问题也更复杂了. 41 # (多谢, S.C.) 42  43 echo 44  45 t=${path_name:11} 46 echo "$path_name, with first 11 chars stripped off = $t" 47 t=${path_name:11:5} 48 echo "$path_name, with first 11 chars stripped off, length 5 = $t" 49  50 echo 51  52 t=${path_name/bozo/clown} 53 echo "$path_name with \"bozo\" replaced by \"clown\" = $t" 54 t=${path_name/today/} 55 echo "$path_name with \"today\" deleted = $t" 56 t=${path_name//o/O} 57 echo "$path_name with all o's capitalized = $t" 58 t=${path_name//o/} 59 echo "$path_name with all o's deleted = $t" 60  61 exit 0

${var/#Pattern/Replacement}

如果变量var前缀匹配模式Pattern,则用Replacement代替匹配模式的字符串.

${var/%Pattern/Replacement}

如果变量var后缀匹配模式Pattern,则用Replacement代替匹配模式的字符串.


例子 9-20. 匹配字符串前缀和后缀的模式

#!/bin/bash 2 # var-match.sh: 3 # Demo of pattern replacement at prefix / suffix of string. 4  v0=abc1234zip1234abc # 初值. 6 echo "v0 = $v0" # abc1234zip1234abc 7 echo 8  # 匹配字符串的前缀(开头). 10 v1=${v0/#abc/ABCDEF} # abc1234zip1234abc 11  # |-| 12 echo "v1 = $v1" # ABCDEF1234zip1234abc 13  # |----| 14  15 # 匹配字符串的后缀(尾部). 16 v2=${v0/�c/ABCDEF} # abc1234zip123abc 17  # |-| 18 echo "v2 = $v2" # abc1234zip1234ABCDEF 19  # |----| 20  21 echo 22  23 # ---------------------------------------------------- 24 # 必须匹配字符串的开头/尾部, 25 #+ 否则不会发生替换. 26 # ---------------------------------------------------- 27 v3=${v0/#123/000} # 匹配,但不是在开头. 28 echo "v3 = $v3" # abc1234zip1234abc 29  # 不会被替换. 30 v4=${v0/3/000} # 匹配,但不是尾部. 31 echo "v4 = $v4" # abc1234zip1234abc 32  # 不会被替换. 33  34 exit 0

${!varprefix*},   ${!varprefix@}

匹配所有前面声明过的变量,并且变量名以varprefix开头.

xyz23=whatever 2 xyz24= 3  a=${!xyz*} # 展开为声明过的并以"xyz". 5 echo "a = $a" # a = xyz23 xyz24 6 a=${!xyz@} # Same as above. 7 echo "a = $a" # a = xyz23 xyz24 8  # Bash, 版本2.04,增加了这个属性.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值