parameter-substitution.html

来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 1,567 行 · 第 1/3 页

HTML
1,567
字号
 21&nbsp; 22&nbsp;#  ${variablename?}结构 23&nbsp;#+ 也能够检查脚本中变量的设置情况. 24&nbsp; 25&nbsp;ThisVariable=Value-of-ThisVariable 26&nbsp;#  注意, 顺便提一下,  27&nbsp;#+ 这个字符串变量可能会被设置一些非法字符. 28&nbsp;: ${ThisVariable?} 29&nbsp;echo "Value of ThisVariable is $ThisVariable". 30&nbsp;echo 31&nbsp;echo 32&nbsp; 33&nbsp; 34&nbsp;: ${ZZXy23AB?"ZZXy23AB has not been set."} 35&nbsp;#  如果变量ZZXy23AB没有被设置的话,  36&nbsp;#+ 那么这个脚本会打印一个错误信息, 然后结束. 37&nbsp; 38&nbsp;# 你可以自己指定错误消息. 39&nbsp;# : ${variablename?"ERROR MESSAGE"} 40&nbsp; 41&nbsp; 42&nbsp;# 等价于:    dummy_variable=${ZZXy23AB?} 43&nbsp;#            dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."} 44&nbsp;# 45&nbsp;#            echo ${ZZXy23AB?} &#62;/dev/null 46&nbsp; 47&nbsp;#  使用命令"set -u"来比较这些检查变量是否被设置的方法. 48&nbsp;# 49&nbsp; 50&nbsp; 51&nbsp; 52&nbsp;echo "You will not see this message, because script already terminated." 53&nbsp; 54&nbsp;HERE=0 55&nbsp;exit $HERE   # 不会在这里退出. 56&nbsp; 57&nbsp;# 事实上, 这个脚本将会以返回值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&nbsp;#!/bin/bash  2&nbsp;# usage-message.sh  3&nbsp;  4&nbsp;: ${1?"Usage: $0 ARGUMENT"}  5&nbsp;#  如果没有提供命令行参数的话, 那么脚本就在这里退出了,   6&nbsp;#+ 并且打印如下错误消息.  7&nbsp;#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT  8&nbsp;  9&nbsp;echo "These two lines echo only if command-line parameter given." 10&nbsp;echo "command line parameter = \"$1\"" 11&nbsp; 12&nbsp;exit 0  # 如果提供了命令行参数, 那么脚本就会在这里退出. 13&nbsp; 14&nbsp;# 分别检查有命令行参数时和没有命令行参数时, 脚本的退出状态. 15&nbsp;# 如果有命令行参数, 那么"$?"就是0. 16&nbsp;# 如果没有的话, 那么"$?"就是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&nbsp;#!/bin/bash  2&nbsp;# length.sh  3&nbsp;  4&nbsp;E_NO_ARGS=65  5&nbsp;  6&nbsp;if [ $# -eq 0 ]  # 这个演示脚本必须有命令行参数.  7&nbsp;then  8&nbsp;  echo "Please invoke this script with one or more command-line arguments."  9&nbsp;  exit $E_NO_ARGS 10&nbsp;fi   11&nbsp; 12&nbsp;var01=abcdEFGH28ij 13&nbsp;echo "var01 = ${var01}" 14&nbsp;echo "Length of var01 = ${#var01}" 15&nbsp;# 现在, 让我们试试在变量中嵌入一个空格. 16&nbsp;var02="abcd EFGH28ij" 17&nbsp;echo "var02 = ${var02}" 18&nbsp;echo "Length of var02 = ${#var02}" 19&nbsp; 20&nbsp;echo "Number of command-line arguments passed to script = ${#@}" 21&nbsp;echo "Number of command-line arguments passed to script = ${#*}" 22&nbsp; 23&nbsp;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&nbsp;# 摘自例子"days-between.sh"的一个函数.  2&nbsp;# 去掉传递进来参数开头的0.  3&nbsp;  4&nbsp;strip_leading_zero () #  去掉从参数中传递进来的,  5&nbsp;{                     #+ 可能存在的开头的0(也可能有多个0).  6&nbsp;  return=${1#0}       #  "1"表示的是"$1" -- 传递进来的参数.  7&nbsp;}                     #  "0"就是我们想从"$1"中删除的子串 -- 去掉零.</PRE></FONT></TD></TR></TABLE>		</P><P>下边是Manfred Schwarb给出的一个更加详细的例子:			<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;strip_leading_zero2 () # 去掉开头可能存在的0(也可能有多个0), 因为如果不取掉的话,  2&nbsp;{                      # Bash就会把这个值当作8进制的值来解释.   3&nbsp;  shopt -s extglob     # 打开扩展的通配(globbing).  4&nbsp;  local val=${1##+(0)} # 使用局部变量, 匹配最长连续的一个或多个0.  5&nbsp;  shopt -u extglob     # 关闭扩展的通配(globbing).  6&nbsp;  _strip_leading_zero2=${val:-0}  7&nbsp;                       # 如果输入为0, 那么返回0来代替"".  8&nbsp;}</PRE></FONT></TD></TR></TABLE>		</P><P>另一个用法示例: <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;echo `basename $PWD`        # 当前工作目录的basename(就是去掉目录名).  2&nbsp;echo "${PWD##*/}"           # 当前工作目录的basename(就是去掉目录名).   3&nbsp;echo  4&nbsp;echo `basename $0`          # 脚本名字.  5&nbsp;echo $0                     # 脚本名字.  6&nbsp;echo "${0##*/}"             # 脚本名字.  7&nbsp;echo  8&nbsp;filename=test.data  9&nbsp;echo "${filename##*.}"      # data 10&nbsp;                            # 文件扩展名.</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&nbsp;#!/bin/bash  2&nbsp;# patt-matching.sh  3&nbsp;  4&nbsp;# 使用# ## % %%来进行参数替换操作的模式匹配. parameter substitution operators.  5&nbsp;  6&nbsp;var1=abcd12345abc6789  7&nbsp;pattern1=a*c  # *(通配符)匹配a - c之间的任意字符.  8&nbsp;  9&nbsp;echo 10&nbsp;echo "var1 = $var1"           # abcd12345abc6789 11&nbsp;echo "var1 = ${var1}"         # abcd12345abc6789 12&nbsp;                              # (另一种形式) 13&nbsp;echo "Number of characters in ${var1} = ${#var1}" 14&nbsp;echo 15&nbsp; 16&nbsp;echo "pattern1 = $pattern1"   # a*c  (匹配'a'到'c'之间的任意字符) 17&nbsp;echo "--------------" 18&nbsp;echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789 19&nbsp;# 最短的可能匹配, 去掉abcd12345abc6789的前3个字符. 20&nbsp;#                     |-|               ^^^^^ 21&nbsp;echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789 22&nbsp;# 最长的可能匹配, 去掉abcd12345abc6789的前12个字符 23&nbsp;#                     |----------|      ^^^^^^ 24&nbsp; 25&nbsp;echo; echo; echo 26&nbsp; 27&nbsp;pattern2=b*9            # 匹配'b'到'9'之间的任意字符 28&nbsp;echo "var1 = $var1"     # 还是abcd12345abc6789 29&nbsp;echo 30&nbsp;echo "pattern2 = $pattern2" 31&nbsp;echo "--------------" 32&nbsp;echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a 33&nbsp;# 最短的可能匹配, 去掉abcd12345abc6789的最后6个字符 34&nbsp;#                               |----|  ^^^^^^^ 35&nbsp;echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a 36&nbsp;# 最长的可能匹配, 去掉abcd12345abc6789的最后12个字符 37&nbsp;#                      |-------------|  ^^^^^^^^ 38&nbsp; 39&nbsp;# 牢记, #和##是从字符串左边开始, 并且去掉左边的字符串,  40&nbsp;#       %和%%从字符串的右边开始, 并且去掉右边的字符串.  41&nbsp;# (译者注: 有个好记的方法, 那就是察看键盘顺序, 记住#在%的左边. ^_^) 42&nbsp;echo 43&nbsp; 44&nbsp;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&nbsp;#!/bin/bash  2&nbsp;# rfe.sh: 修改文件扩展名.  3&nbsp;#  4&nbsp;# 用法:		rfe old_extension new_extension  5&nbsp;#  6&nbsp;# 示例:  7&nbsp;# 将指定目录中所有的*.gif文件都重命名为*.jpg,  8&nbsp;# 用法:		rfe gif jpg  9&nbsp; 10&nbsp; 11&nbsp;E_BADARGS=65 12&nbsp; 13&nbsp;case $# in 14&nbsp;  0|1)             # 竖线"|"在这里表示"或"操作. 15&nbsp;  echo "Usage: `basename $0` old_file_suffix new_file_suffix" 16&nbsp;  exit $E_BADARGS  # 如果只有0个或1个参数的话, 那么就退出脚本. 17&nbsp;  ;; 18&nbsp;esac 19&nbsp; 20&nbsp; 21&nbsp;for filename in *.$1 22&nbsp;# 以第一个参数为扩展名的全部文件的列表. 23&nbsp;do 24&nbsp;  mv $filename ${filename%$1}$2 25&nbsp;  #  把筛选出来的文件的扩展名去掉, 因为筛选出来的文件的扩展名都是第一个参数, 26&nbsp;  #+ 然后把第2个参数作为扩展名, 附加到这些文件的后边. 27&nbsp;done 28&nbsp;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?