1. 程式人生 > 實用技巧 >四、Shell變數之四變數的子串

四、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、取變數的長度

賦值ni hao da hai 給KING
[root@node1 tmp]# KING="ni hao da hai"
[root@node1 tmp]# echo $KING
ni hao da hai

列印變數值的長度
[root@node1 tmp]# 
echo ${#KING} 13 [root@node1 tmp]# echo $KING|wc -L 13 [root@node1 tmp]# expr length "$KING" 13 [root@node1 tmp]# echo $KING|awk '{print length($0)}' 13 #空格需要算一個字元

案例2:擷取YWX變數的內容

[root@node1 tmp]# YWX="I am ywx linux, welcome to oldboy training"
[root@node1 tmp]# echo $YWX
I am ywx linux, welcome to oldboy training

從第2個字元之後開始擷取,預設擷取後面字元的全部,第2個字元不包含在內,也可理解為刪除前面的多個字元。

[root@node1 tmp]# echo ${YWX:2}
am ywx linux, welcome to oldboy training

擷取變數的內容,從第2個字元之後開始擷取,擷取2個字元。

[root@node1 tmp]# echo ${YWX:2:2}
am
[root@node1 tmp]# echo ${YWX}|cut -c 3-4
am

案例3、從變數$YWX內容的開頭開始刪除最短匹配“a*C”及“a*c”的子串。

[root@node1 tmp]# YWX=abcABC123ABCabc
[root@node1 tmp]# echo $YWX
abcABC123ABCabc
開頭開始刪除最短匹配“a*C”的子串。
[root@node1 tmp]# echo ${YWX#a*C}
123ABCabc
#從開頭開始刪除最短匹配“a*C”的子串。
開頭開始刪除最短匹配“a*c”的子串
[root@node1 tmp]# echo ${YWX#a*c}
ABC123ABCabc
#從開頭開始刪除最短匹配“a*c”的子串。

案例4、從變數$YWX開頭開始刪除最長匹配“a*C”及“a*c”的子串

[root@node1 tmp]# YWX=abcABC123ABCabc
[root@node1 tmp]# echo $YWX
abcABC123ABCabc
開頭開始刪除最長匹配“a*C”的子串。
[root@node1 tmp]# echo ${YWX##a*C}
abc
#從開頭開始刪除最長匹配“a*C”的子串。
開頭開始刪除最長匹配“a*c”的子串
[root@node1 tmp]# echo ${YWX##a*c}

[root@node1 tmp]# 
#開頭開始刪除最長匹配“a*c”的子串

案例5、從變數$YWX結尾開始刪除最短匹配“a*C”及“a*c”的子串。

[root@node1 tmp]# YWX=abcABC123ABCabc
[root@node1 tmp]# echo $YWX
abcABC123ABCabc
從結尾開始刪除最短匹配“a*C”的子串。
[root@node1 tmp]# echo ${YWX%a*C}
abcABC123ABCabc
#因為從結尾開始“a*C”沒有匹配上任何子串,因此,沒有刪除任何字元,原樣輸出
從結尾開始刪除最短匹配“a*c”的子串。
[root@node1 tmp]# echo ${YWX%a*c}
abcABC123ABC
#從結尾開始刪除最短匹配“a*c”,即刪除了結尾的abc三個字元。

案例6、從變數$YWX結尾開始刪除最長匹配“a*C”及“a*c”的子串。

[root@node1 tmp]# YWX=abcABC123ABCabc
[root@node1 tmp]# echo $YWX
abcABC123ABCabc
從結尾開始刪除最長匹配“a*C”的子串。
[root@node1 tmp]# echo ${YWX%%a*C}
abcABC123ABCabc
#因為從結尾開始“a*C”沒有匹配上任何子串,因此,沒有刪除任何字元,原樣輸出
從結尾開始刪除最短匹配“a*c”的子串。
[root@node1 tmp]# echo ${YWX%%a*c}

[root@node1 tmp]#
#從結尾開始刪除最長匹配“a*c”的字串,即刪除全部字元。

刪除匹配總結

有關上述匹配刪除的小結:
·#表示從開頭刪除匹配最短。
·##表示從開頭刪除匹配最長。
·%表示從結尾刪除匹配最短。
·%%表示從結尾刪除匹配最長。
·a*c表示匹配的字串,*表示匹配所有,a*c匹配開頭為a、中間為任意多個字元、結尾為c的字串。
·a*C表示匹配的字串,*表示匹配所有,a*C匹配開頭為a、中間為任意多個字元、結尾為C的字串。

案例7、使用king字串代替變數$YWX匹配的ywx字串。

[root@node1 tmp]# YWX="I am ywx,yes,ywx,ywx"
[root@node1 tmp]# echo $YWX
I am ywx,yes,ywx,ywx
只替換最近的一個ywx
[root@node1 tmp]# echo ${YWX/ywx/king}
I am king,yes,ywx,ywx
替換全部的ywx
[root@node1 tmp]# echo ${YWX//ywx/king}
I am king,yes,king,king

二、Shell特殊擴充套件變數

${parameter:-word}
如果parameter的變臉值為空或未賦值,則返回word字串並替代變數的值。用法:如果變數未定義,則返回備用值,防止變數為空值或因未定義而導致異常。

${parameter:=word}
如果parameter的變臉值為空或未賦值,則設定這個變臉值為word,並返回其值。位置變數和特殊變數不使用。用法:基本通${parameter:-word},但該變數又額外給parameter變臉賦值了。

${parameter:?word}
如果parameter的變臉值為空或未賦值,那麼word字串將被作為標準錯誤輸出,否則輸出變數的值。用法:用於捕捉由於變數未定義而導致的錯誤,並退出程式。

${parameter:+word}
如果parameter的變臉值為空或未賦值,則什麼都不做,否則word字串將替代變數的值

案例1、${parameter:-word}功能實踐

${parameter:-word}的作用是如果parameter變數值為空或未賦值,則會返回word字串替代變數的值。

[root@node1 tmp]# echo $test   #$test未賦值

[root@node1 tmp]# result=${test:-unset}
[root@node1 tmp]# echo $result
unset
[root@node1 tmp]# echo $test  

#對於${test:-UNSET},當test變數沒值時,就返回變數結尾設定的UNSET字串。
[root@node1 tmp]# test="kaka"
[root@node1 tmp]# echo $test
kaka
[root@node1 tmp]# result=${test:-unset}
[root@node1 tmp]# echo $result
kaka
#當test變數有值時,就列印result變數,返回test變數的內容。

案例2:${parameter:=word}功能實踐

${parameter:=word}的作用是:如果parameter變數值為空或未賦值,就設定這個變數值為word,並返回其值。位置變數和特殊變數不適用。

[root@node1 tmp]# unset test
[root@node1 tmp]# unset result
[root@node1 tmp]# echo $test

[root@node1 tmp]# echo $result

[root@node1 tmp]# 
#取消test和result的賦值
[root@node1 tmp]# echo $test

[root@node1 tmp]# result=${test:=unset}
[root@node1 tmp]# echo $result
unset
[root@node1 tmp]# echo $test
unset
#最後會把unset賦值給test變數

[root@node1 tmp]# test="kaka"
[root@node1 tmp]# result=${test:=unset}
[root@node1 tmp]# echo $result
kaka

#當變數(result)值裡的變數(test)值沒有定義時,會給變數(result)賦值“:=”後面的內容,同時會把“:=”後面的內容賦值給變數(result)值裡沒有定義的變數(test)。這個變數的功能可以解決變數沒有定義的問題,並確保沒有定義的變數始終有值。

案例3、${parameter:?word}功能實踐

{parameter:?word}的作用是:如果parameter變數值為空或未賦值,那麼word字串將被作為標準錯誤輸出,否則輸出變數的值。

[root@node1 tmp]# echo $key

[root@node1 tmp]# echo ${key:?not defined}
-bash: key: not defined
#key沒有賦值則把not defined作為標準錯誤輸出

[root@node1 tmp]# key=king
[root@node1 tmp]# echo ${key:?not defined}
king

案例4.${parameter:+word}功能實踐

${parameter:+word}的作用是:如果parameter變數值為空或未賦值,則什麼都不做,否則word字串將替代變數的值。

[root@node1 tmp]# echo $seal

[root@node1 tmp]# echo ${seal:+word}

[root@node1 tmp]# 
#seal的值未空或沒有賦值,則什麼也不用做
[root@node1 tmp]# seal="nihao"
[root@node1 tmp]# echo ${seal:+word}
word
#如果變數有值,則列印word

案例5:實現Apache服務啟動指令碼/etc/init.d/httpd

yum install -y httpd

#!/bin/bash
#
# httpd        Startup script for the Apache HTTP Server
#..skip…
# Start httpd in the C locale by default.
HTTPD_LANG=${HTTPD_LANG-"C"} #<==如果HTTPD_LANG變數沒有定義或為空,則列印HTTPD_
                                   LANG變數返回C值。
#<==這一步定義方法的目的是防止變數值為空或未定義。使用的是(${parameter-word}用法,
        此處省略了冒號)。
# This will prevent initlog from swallowing up a pass-phrase prompt if
# mod_ssl needs a pass-phrase from the user.
INITLOG_ARGS=""
# Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
# with the thread-based "worker" MPM; BE WARNED that some modules may not
# work correctly with a thread-based MPM; notably PHP will refuse to start.
# Path to the apachectl script, server binary, and short-form for messages.
apachectl=/usr/sbin/apachectl
httpd=${HTTPD-/usr/sbin/httpd}
#<==如果HTTPD變數沒有定義或為空,則列印HTTPD_LANG變數返回/usr/sbin/httpd的值。
#<==此步定義方法的目的是防止變數值為空或未定義。使用的是(${parameter-word}用法,冒號省略了)。
prog=httpdpidfile=${PIDFILE-/var/run/httpd.pid}
lockfile=${LOCKFILE-/var/lock/subsys/httpd}
RETVAL=0…skip…
exit $RETVAL

案例6:刪除7天前的過期資料備份。

如果忘記了定義path變數,又不希望path值為空值,就可以定義/tmp替代path空值的返回值

[root@oldboy test]# cat del.sh
find ${path - /tmp} -name "*.tar.gz" -type f -mtime +7|xargs rm -f
[root@oldboy test]# sh -x del.sh
+ xargs rm -f
+ find /tmp -name '*.tar.gz' -type f -mtime +7  #<==執行時,系統會自動刪除/tmp下的檔案。
如果忘了定義path變數,並且還未做特殊變數定義,那麼命令就會出現意外
[root@oldboy tmp]# cat a.sh
find ${path} -name "*.tar.gz" -type f -mtime +7|xargs rm -f
[root@oldboy tmp]# sh -x a.sh
+ xargs rm -f
+ find -name '*.tar.gz' -type f -mtime +7 #<==這條命令明顯沒有指定路徑,因此將會導致異常。