首頁>技術>

《Shell中的替換規則》

${parameter}

與$parameter相同,代表引數parameter的值。在某些特定環境下,只有不太模糊或者說是精確的的${parameter}形式有效。

可用於將變數與字串連線

your_id=${USER}-on-${HOSTNAME}echo "${your_id}"	# cory-on-cory-server# Old $PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binecho "Old \$PATH = $PATH" PATH=${PATH}:/opt/bin# New $PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/binecho "New \$PATH = $PATH"
${parameter-default},${parameter:-default}

如果parameter未設定,則使用default預設值

var1=1var2=2echo ${var1-$var2}	# 1echo ${var3-$var2}	# 2# 如果變數${username}未設定,則輸出命令`whoami`的值echo ${username-`whoami`}	# cory

要注意${parameter-default}和${parameter:-default}幾乎相等。 多出的冒號 ':'僅在引數已宣告但為null時才起作用。

#!/bin/bash# param-sub.sh#  Whether a variable has been declared#+ affects triggering of the default option#+ even if the variable is null.# 變數是否宣告影響預設值的觸發,即使變數為空username0=echo "username0 has been decalare, but is set to null."echo "username0 = ${username0-`whoami`}"# Will not echo.# 不會輸出echoecho username1 has not been declared.echo "username1 = ${username1-`whoami`}"# Will echo.# 會輸出username2=echo "username2 has been declared, but is set to null."echo "username2 = ${username2:-`whoami`}"#                            ^# Will echo because of :- rather than just - in condition test.# Compare to first instance, above.# 會輸出,因為有一個冒號## Once again:variable=# variable has been declared, but is set to null.echo "${variable-0}"    # (no output)echo "${variable:-1}"   # 1#               ^unset variableecho "${variable-2}"    # 2echo "${variable:-3}"   # 3exit 0

結果輸出:

username0 has been decalare, but is set to null.username0 =username1 has not been declared.username1 = coryusername2 has been declared, but is set to null.username2 = cory123

預設引數構造可用於在指令碼中提供“缺少的”命令列引數。

#!/bin/bash# default.sh# 如果執行指令碼沒有傳入引數,則使用預設值param=${1:-"default_param"}echo "${param}"

結果輸出:

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

如果未設定引數,請將其設定為預設值。兩種形式幾乎相等。 僅當$parameter已宣告且為null時,冒號':'才有所不同,與${parameter:-default}用法一致

echo ${var=abc}	# abc# 因為var已經被強制設定預設值,所以輸出為定義值echo ${var=xyz}	# abc
${parameter+alt_value}, ${parameter:+alt_value}

如果設定引數,使用alt_value值,否則使用空值。

兩種形式幾乎相等。 僅當$parameter已宣告且為null時,冒號':'才有所不同,檢視如下例子

#!/bin/bashecho "###### \${parameter+alt_value} ########"echoa=${param1+cory}echo "a = $a"      # a =param2=a=${param2+cory}echo "a = $a"      # a = coryparam3=123a=${param3+cory}echo "a = $a"      # a = coryechoecho "###### \${parameter:+alt_value} ########"echoa=${param4:+cory}echo "a = $a"      # a =param5=a=${param5:+cory}echo "a = $a"      # a =# Different result from   a=${param5+cory}param6=123a=${param6:+cory}echo "a = $a"      # a = cory

結果:

###### ${parameter+alt_value} ########a =a = corya = cory###### ${parameter:+alt_value} ########a =a =a = cory
${parameter?err_msg}, ${parameter:?err_msg}

如果設定引數,使用引數值,否則列印輸出err_msg資訊,並且狀態1退出指令碼

兩種形式幾乎相等。 僅當$parameter已宣告且為null時,冒號':'才有所不同,與${parameter+alt_value}使用方法類似

#!/bin/bash# 校驗系統環境變數# 預防性維護# 例如:如果$USER,控制檯上的使用者,未設定,機器將無法識別: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}  echo  echo "Name of the machine is $HOSTNAME."  echo "You are $USER."  echo "Your home directory is $HOME."  echo "Your mail INBOX is located in $MAIL."  echo  echo "If you are reading this message,"  echo "critical environmental variables have been set."  echo  echo# ------------------------------------------------------#  The ${variablename?} construction can also check#+ for variables set within the script.ThisVariable=Value-of-ThisVariable#  Note, by the way, that string variables may be set#+ to characters disallowed in their names.: ${ThisVariable?}echo "Value of ThisVariable is $ThisVariable".echo; echo: ${ZZXy23AB?"ZZXy23AB has not been set."}#  Since ZZXy23AB has not been set,#+ then the script terminates with an error message.# You can specify the error message.# : ${variablename?"ERROR MESSAGE"}# Same result with:   dummy_variable=${ZZXy23AB?}#                     dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."}##                     echo ${ZZXy23AB?} >/dev/null#  Compare these methods of checking whether a variable has been set#+ with "set -u" . . .echo "You will not see this message, because script already terminated."HERE=0exit $HERE   # Will NOT exit here.# In fact, this script will return an exit status (echo $?) of 1.

結果:

Name of the machine is cory-server.You are cory.Your home directory is /home/cory.Your mail INBOX is located in /var/mail/cory.If you are reading this message,critical environmental variables have been set.Value of ThisVariable is Value-of-ThisVariable../err_msg.sh: line 34: ZZXy23AB: ZZXy23AB has not been set.

這裡們需要了解冒號(:)是內嵌命令,官方給的解釋:

: [arguments]

No effect; the command does nothing beyond expanding arguments and performing any specified redirections. The return status is zero.

也就是冒號命令本身沒有實際效果,該命令除了擴充套件引數和執行任何指定的重定向外,什麼也不 做。 返回狀態為零。

但是與當前的${parameter?}結合進行引數校驗

${#var}

字串長度($var中的字元數)。對於陣列,$ {#array}是陣列中第一個元素的長度。

例外情況:

$ {#*}和$ {#@}給出位置引數的數量。

對於陣列,$ {#array [*]}和$ {#array [@]}給出陣列中元素的數量。

#!/bin/bash# length.shE_NO_ARGS=65if [ $# -eq 0 ]  # Must have command-line args to demo script.then  echo "Please invoke this script with one or more command-line arguments."  exit $E_NO_ARGSfivar01=abcdEFGH28ijecho "var01 = ${var01}"echo "Length of var01 = ${#var01}"# Now, let's try embedding a space.var02="abcd EFGH28ij"echo "var02 = ${var02}"echo "Length of var02 = ${#var02}"echo "Number of command-line arguments passed to script = ${#@}"echo "Number of command-line arguments passed to script = ${#*}"exit 0

結果:

pwd # /home/coryecho `basename $PWD` # coryecho "${PWD##*/}" # coryfilename=test.dataecho "${filename##*.}"	# data
${var%Pattern},${var%%Pattern}

${var%Pattern}從$var中刪除與$var後端匹配的$Pattern最短部分。

#!/bin/bash# Pattern matching  using the # ## % %% parameter substitution operators.var1=abcd12345abc6789pattern1=a*c  # * (wild card) matches everything between a - c.echoecho "var1 = $var1"           # abcd12345abc6789echo "var1 = ${var1}"         # abcd12345abc6789                              # (alternate form)echo "Number of characters in ${var1} = ${#var1}"echoecho "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')echo "--------------"echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789# Shortest possible match, strips out first 3 characters  abcd12345abc6789#                                                       ^^^^^                   |-|echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789# Longest possible match, strips out first 12 characters  abcd12345abc6789#                                    ^^^^^                |----------|echo; echo; echopattern2=b*9            # everything between 'b' and '9'echo "var1 = $var1"     # Still  abcd12345abc6789echoecho "pattern2 = $pattern2"echo "--------------"echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a# Shortest possible match, strips out last 6 characters  abcd12345abc6789#                                     ^^^^                         |----|echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a# Longest possible match, strips out last 12 characters  abcd12345abc6789#                                    ^^^^                 |-------------|# Remember, # and ## work from the left end (beginning) of string,#           % and %% work from the right end.echoexit 0

結果:

var1 = abcd12345abc6789var1 = abcd12345abc6789Number of characters in abcd12345abc6789 = 16pattern1 = a*c--------------${var1#$pattern1}  = d12345abc6789${var1##$pattern1} = 6789var1 = abcd12345abc6789pattern2 = b*9--------------${var1%pattern2}  = abcd12345a${var1%%pattern2} = a

另外一個例子:

更改字尾名

#!/bin/bash# rfe.sh: Renaming file extensions.##         rfe old_extension new_extension## Example:# To rename all *.gif files in working directory to *.jpg,#          rfe gif jpgE_BADARGS=65case $# in  0|1)             # The vertical bar means "or" in this context.  echo "Usage: `basename $0` old_file_suffix new_file_suffix"  exit $E_BADARGS  # If 0 or 1 arg, then bail out.  ;;esacfor filename in *.$1# Traverse list of files ending with 1st argument.do  mv $filename ${filename%$1}$2  #  Strip off part of filename matching 1st argument,  #+ then append 2nd argument.doneexit 0
${var:pos}

變數var從偏移量pos開始擴充套件。

me=coryecho ${me:2}	# ry
${var:pos:len}

從偏移pos擴充套件到最多len個變數var的字元。

me=coryecho ${me:1:2}	# or
${var/Patter/Replacement}

Pattern的第一個匹配項,在var中用Replacement替換。

sen="I am god" echo ${sen/god/cory}	# I am cory
${var//Pattern//Replacement}

全域性替換。var中所有Pattern的匹配項都用Replacement替換。

#!/bin/bashvar1=abcd-1234-defgecho "var1 = $var1"t=${var1#*-*}echo "var1 (with everything, up to and including first - stripped out) = $t"#  t=${var1#*-}  works just the same,#+ since # matches the shortest string,#+ and * matches everything preceding, including an empty string.# 匹配最短字串 空字串也包含t=${var1##*-*}echo "If var1 contains a \"-\", returns empty string...   var1 = $t"t=${var1%*-*}echo "var1 (with everything from the last - on stripped out) = $t"echo# -------------------------------------------path_name=/home/bozo/ideas/thoughts.for.today# -------------------------------------------echo "path_name = $path_name"t=${path_name##/*/}echo "path_name, stripped of prefixes = $t"# Same effect as   t=`basename $path_name` in this particular case.#  t=${path_name%/}; t=${t##*/}   is a more general solution,#+ but still fails sometimes.#  If $path_name ends with a newline, then `basename $path_name` will not work,#+ but the above expression will.# 如果變數包含新行newline,使用函式basename就會有問題,而使用上邊方法則沒有問題t=${path_name%/*.*}# Same effect as   t=`dirname $path_name`echo "path_name, stripped of suffixes = $t"# These will fail in some cases, such as "../", "/foo////", # "foo/", "/".#  Removing suffixes, especially when the basename has no suffix,#+ but the dirname does, also complicates matters.echot=${path_name:11}echo "$path_name, with first 11 chars stripped off = $t"t=${path_name:11:5}echo "$path_name, with first 11 chars stripped off, length 5 = $t"echot=${path_name/bozo/clown}echo "$path_name with \"bozo\" replaced  by \"clown\" = $t"t=${path_name/today/}echo "$path_name with \"today\" deleted = $t"t=${path_name//o/O}echo "$path_name with all o's capitalized = $t"t=${path_name//o/}echo "$path_name with all o's deleted = $t"exit 0

結果:

var1 = abcd-1234-defgvar1 (with everything, up to and including first - stripped out) = 1234-defgIf var1 contains a "-", returns empty string...   var1 =var1 (with everything from the last - on stripped out) = abcd-1234path_name = /home/bozo/ideas/thoughts.for.todaypath_name, stripped of prefixes = thoughts.for.todaypath_name, stripped of suffixes = /home/bozo/ideas/home/bozo/ideas/thoughts.for.today, with first 11 chars stripped off = ideas/thoughts.for.today/home/bozo/ideas/thoughts.for.today, with first 11 chars stripped off, length 5 = ideas/home/bozo/ideas/thoughts.for.today with "bozo" replaced  by "clown" = /home/clown/ideas/thoughts.for.today/home/bozo/ideas/thoughts.for.today with "today" deleted = /home/bozo/ideas/thoughts.for./home/bozo/ideas/thoughts.for.today with all o's capitalized = /hOme/bOzO/ideas/thOughts.fOr.tOday/home/bozo/ideas/thoughts.for.today with all o's deleted = /hme/bz/ideas/thughts.fr.tday
${var/#Pattern/Replacement}

如果var的字首與Pattern匹配,則將Replacement替換為Pattern。

echo ${me}	# coryecho ${me/#c/g}	# gory
${var/%Pattern/Replacement}

如果var的字尾與Pattern匹配,則將Replacement替換為Pattern。

#!/bin/bash# var-match.sh:# Demo of pattern replacement at prefix / suffix of string.v0=abc1234zip1234abc    # Original variable.echo "v0 = $v0"         # abc1234zip1234abcecho# Match at prefix (beginning) of string.v1=${v0/#abc/ABCDEF}    # abc1234zip1234abc                        # |-|echo "v1 = $v1"         # ABCDEF1234zip1234abc                        # |----|# Match at suffix (end) of string.v2=${v0/%abc/ABCDEF}    # abc1234zip123abc                        #              |-|echo "v2 = $v2"         # abc1234zip1234ABCDEF                        #               |----|echo#  ----------------------------------------------------#  Must match at beginning / end of string,#+ otherwise no replacement results.#  ----------------------------------------------------v3=${v0/#123/000}       # Matches, but not at beginning.echo "v3 = $v3"         # abc1234zip1234abc# NO REPLACEMENT.v4=${v0/%123/000}       # Matches, but not at end.echo "v4 = $v4"         # abc1234zip1234abc# NO REPLACEMENT.exit 0

結果:

v0 = abc1234zip1234abcv1 = ABCDEF1234zip1234abcv2 = abc1234zip1234ABCDEFv3 = abc1234zip1234abcv4 = abc1234zip1234abc
${!varprefix*},${!varprefix@}

匹配所有以varprefix開頭的先前宣告的變數的名稱。間接引用帶有感嘆號(!)

# 這是間接引用的變體,只是帶了個*或者@.# Bash, version 2.04, adds this feature.xyz23=whateverxyz24=a=${!xyz*}         #  Expands to *names* of declared variables# ^ ^   ^           + beginning with "xyz".echo "a = $a"      #  a = xyz23 xyz24a=${!xyz@}         #  Same as above.echo "a = $a"      #  a = xyz23 xyz24echo "---"abc23=something_elseb=${!abc*}echo "b = $b"      #  b = abc23c=${!b}            # 常見的間接引用echo $c            #  something_else

12
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 阿里自爆效能最佳化100+小技巧,Github已獲贊68.7K