parameter-substitution.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 1,567 行 · 第 1/3 页
HTML
1,567 行
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 $?).</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="USAGEMESSAGE"></A><P><B>例子 9-16. 参数替换和<SPANCLASS="QUOTE">"usage"</SPAN>消息(译者注: 通常就是帮助信息)</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # usage-message.sh 3 4 : ${1?"Usage: $0 ARGUMENT"} 5 # 如果没有提供命令行参数的话, 那么脚本就在这里退出了, 6 #+ 并且打印如下错误消息. 7 # usage-message.sh: 1: Usage: usage-message.sh ARGUMENT 8 9 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.</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="FORMALPARA"><P><B>参数替换与(或)扩展. </B><ANAME="PSUB2"></A>下边这些表达式都是对如何<TTCLASS="REPLACEABLE"><I>在</I></TT><BCLASS="COMMAND">expr</B>字符串操作中进行<BCLASS="COMMAND">match</B>的补充. 参考<AHREF="moreadv.html#EX45">例子 12-9</A>). 这些特定的使用方法一般都用来解析文件所在的目录名. </P></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="PSOREX1"></A>变量长度/子串删除</B></P><DL><DT><KBDCLASS="USERINPUT">${#var}</KBD></DT><DD><P><KBDCLASS="USERINPUT">字符串长度</KBD>(变量<CODECLASS="VARNAME">$var</CODE>得字符个数). 对于<AHREF="arrays.html#ARRAYREF">array</A>来说, <BCLASS="COMMAND">${#array}</B>表示的是数组中第一个元素的长度. </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P> 例外情况: <P></P><UL><LI><P> <BCLASS="COMMAND">${#*}</B>和<BCLASS="COMMAND">${#@}</B>表示<EM>位置参数的个数</EM>. </P></LI><LI><P> 对于数组来说, <BCLASS="COMMAND">${#array[*]}</B>和<BCLASS="COMMAND">${#array[@]}</B>表示数组中元素的个数. </P></LI></UL> </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="LENGTH"></A><P><B>例子 9-17. 变量长度</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # length.sh 3 4 E_NO_ARGS=65 5 6 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</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><KBDCLASS="USERINPUT">${var#Pattern}</KBD>, <KBDCLASS="USERINPUT">${var##Pattern}</KBD></DT><DD><P>从变量<CODECLASS="VARNAME">$var</CODE>的<TTCLASS="REPLACEABLE"><I>开头</I></TT>删除最短或最长匹配<CODECLASS="VARNAME">$Pattern</CODE>的子串. (译者注: 这是一个很常见的用法, 请读者牢记, 一个<SPANCLASS="QUOTE">"#"</SPAN>表示匹配最短, <SPANCLASS="QUOTE">"##"</SPAN>表示匹配最长.) </P><P><AHREF="contributed-scripts.html#DAYSBETWEEN">例子 A-7</A>中的一个用法示例:<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 # 摘自例子"days-between.sh"的一个函数. 2 # 去掉传递进来参数开头的0. 3 4 strip_leading_zero () # 去掉从参数中传递进来的, 5 { #+ 可能存在的开头的0(也可能有多个0). 6 return=${1#0} # "1"表示的是"$1" -- 传递进来的参数. 7 } # "0"就是我们想从"$1"中删除的子串 -- 去掉零.</PRE></FONT></TD></TR></TABLE> </P><P>下边是Manfred Schwarb给出的一个更加详细的例子: <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 strip_leading_zero2 () # 去掉开头可能存在的0(也可能有多个0), 因为如果不取掉的话, 2 { # Bash就会把这个值当作8进制的值来解释. 3 shopt -s extglob # 打开扩展的通配(globbing). 4 local val=${1##+(0)} # 使用局部变量, 匹配最长连续的一个或多个0. 5 shopt -u extglob # 关闭扩展的通配(globbing). 6 _strip_leading_zero2=${val:-0} 7 # 如果输入为0, 那么返回0来代替"". 8 }</PRE></FONT></TD></TR></TABLE> </P><P>另一个用法示例: <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo `basename $PWD` # 当前工作目录的basename(就是去掉目录名). 2 echo "${PWD##*/}" # 当前工作目录的basename(就是去掉目录名). 3 echo 4 echo `basename $0` # 脚本名字. 5 echo $0 # 脚本名字. 6 echo "${0##*/}" # 脚本名字. 7 echo 8 filename=test.data 9 echo "${filename##*.}" # data 10 # 文件扩展名.</PRE></FONT></TD></TR></TABLE> </P></DD><DT><ANAME="PCTPATREF"></A><KBDCLASS="USERINPUT">${var%Pattern}</KBD>, <KBDCLASS="USERINPUT">${var%%Pattern}</KBD></DT><DD><P>从变量<CODECLASS="VARNAME">$var</CODE>的<TTCLASS="REPLACEABLE"><I>结尾</I></TT>删除最短或最长匹配<CODECLASS="VARNAME">$Pattern</CODE>的子串. (译者注: 这是一个很常见的用法, 请读者牢记, 一个<SPANCLASS="QUOTE">"%"</SPAN>表示匹配最短, <SPANCLASS="QUOTE">"%%"</SPAN>表示匹配最长.) </P></DD></DL></DIV><P>Bash的<AHREF="bashver2.html#BASH2REF">版本2</A>添加了一些额外选项. </P><DIVCLASS="EXAMPLE"><HR><ANAME="PATTMATCHING"></A><P><B>例子 9-18. 参数替换中的模式匹配</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # patt-matching.sh 3 4 # 使用# ## % %%来进行参数替换操作的模式匹配. parameter substitution operators. 5 6 var1=abcd12345abc6789 7 pattern1=a*c # *(通配符)匹配a - c之间的任意字符. 8 9 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的前3个字符. 20 # |-| ^^^^^ 21 echo '${var1##$pattern1} =' "${var1##$pattern1}" # 6789 22 # 最长的可能匹配, 去掉abcd12345abc6789的前12个字符 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 # 最短的可能匹配, 去掉abcd12345abc6789的最后6个字符 34 # |----| ^^^^^^^ 35 echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a 36 # 最长的可能匹配, 去掉abcd12345abc6789的最后12个字符 37 # |-------------| ^^^^^^^^ 38 39 # 牢记, #和##是从字符串左边开始, 并且去掉左边的字符串, 40 # %和%%从字符串的右边开始, 并且去掉右边的字符串. 41 # (译者注: 有个好记的方法, 那就是察看键盘顺序, 记住#在%的左边. ^_^) 42 echo 43 44 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="RFE"></A><P><B>例子 9-19. 修改文件扩展名<SPANCLASS="TOKEN">:</SPAN></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # rfe.sh: 修改文件扩展名. 3 # 4 # 用法: rfe old_extension new_extension 5 # 6 # 示例: 7 # 将指定目录中所有的*.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 #+ 然后把第2个参数作为扩展名, 附加到这些文件的后边. 27 done 28
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?