自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux Bash腳本15分鐘進(jìn)階教程

系統(tǒng) Linux
這里的技術(shù)技巧最初是來自谷歌的“Testing on the Toilet” (TOTT)。這里是一個(gè)修訂和擴(kuò)增版本。

Linux Bash腳本15分鐘進(jìn)階教程

這里的技術(shù)技巧最初是來自谷歌的“Testing on the Toilet” (TOTT)。這里是一個(gè)修訂和擴(kuò)增版本。

腳本安全

我的所有bash腳本都以下面幾句為開場(chǎng)白: 

  1. #!/bin/bash  
  2. set -o nounset  
  3. set -o errexit 

這樣做會(huì)避免兩種常見的問題:

  1. 引用未定義的變量(缺省值為“”)
  2. 執(zhí)行失敗的命令被忽略

需要注意的是,有些Linux命令的某些參數(shù)可以強(qiáng)制忽略發(fā)生的錯(cuò)誤,例如“mkdir -p” 和 “rm -f”。

還要注意的是,在“errexit”模式下,雖然能有效的捕捉錯(cuò)誤,但并不能捕捉全部失敗的命令,在某些情況下,一些失敗的命令是無法檢測(cè)到的。(更多細(xì)節(jié)請(qǐng)參考這個(gè)帖子。)

腳本函數(shù)

在bash里你可以定義函數(shù),它們就跟其它命令一樣,可以隨意的使用;它們能讓你的腳本更具可讀性: 

  1. ExtractBashComments() {  
  2.   egrep "^#"  
  3.  
  4. cat myscript.sh | ExtractBashComments | wc  
  5. comments=$(ExtractBashComments < myscript.sh) 

還有一些例子: 

  1. SumLines() {    
  2. # iterating over stdin - similar to awk     
  3.   local sum=0  
  4.   local line=””  
  5.   while read line ; do  
  6.       sum=$((${sum} + ${line}))  
  7.   done  
  8.   echo ${sum 
  9.  
  10.  
  11. SumLines < data_one_number_per_line.txt  
  12. log() {    
  13. # classic logger  
  14.  local prefix="[$(date +%Y/%m/%d\ %H:%M:%S)]: "  
  15.  echo "${prefix} $@" >&2  
  16.   
  17. log "INFO" "a message" 

盡可能的把你的bash代碼移入到函數(shù)里,僅把全局變量、常量和對(duì)“main”調(diào)用的語句放在最外層。

變量注解

Bash里可以對(duì)變量進(jìn)行有限的注解。最重要的兩個(gè)注解是:

  1. local(函數(shù)內(nèi)部變量)
  2. readonly(只讀變量) 
  1. # a useful idiom: DEFAULT_VAL can be overwritten  
  2. #       with an environment variable of the same name  
  3. readonly DEFAULT_VAL=${DEFAULT_VAL:-7}  
  4.  
  5. myfunc() {  
  6. # initialize a local variable with the global default  
  7.  local some_var=${DEFAULT_VAL}  
  8.  ...  

這樣,你可以將一個(gè)以前不是只讀變量的變量聲明成只讀變量: 

  1. x=5  
  2. x=6  
  3. readonly x  
  4. x=7    
  5. # failure 

盡量對(duì)你bash腳本里的所有變量使用local或readonly進(jìn)行注解。

用$()代替反單引號(hào)(`)

反單引號(hào)很難看,在有些字體里跟正單引號(hào)很相似。$()能夠內(nèi)嵌使用,而且避免了轉(zhuǎn)義符的麻煩。 

  1. # both commands below print out: A-B-C-D  
  2. echo "A-`echo B-\`echo C-\\\`echo D\\\`\``"  
  3. echo "A-$(echo B-$(echo C-$(echo D)))" 

用[[]](雙層中括號(hào))替代[]

使用[[]]能避免像異常的文件擴(kuò)展名之類的問題,而且能帶來很多語法上的改進(jìn),而且還增加了很多新功能:

單中括號(hào): 

  1. "${name}" \> "a" -o ${name} \< "m" ] 

雙中括號(hào) 

  1. [[ "${name}" > "a" && "${name}" < "m"  ]] 

正則表達(dá)式/Globbing

使用雙中括號(hào)帶來的好處用下面幾個(gè)例子最能表現(xiàn): 

  1. t="abc123"  
  2. [[ "$t" == abc* ]]   
  3. true (globbing比較)  
  4. [[ "$t" == "abc*" ]]   
  5. false (字面比較)  
  6. [[ "$t" =~ [abc]+[123]+ ]]  
  7. true (正則表達(dá)式比較)  
  8. [[ "$t" =~ "abc*" ]]    
  9. false (字面比較) 

注意,從bash 3.2版開始,正則表達(dá)式和globbing表達(dá)式都不能用引號(hào)包裹。如果你的表達(dá)式里有空格,你可以把它存儲(chǔ)到一個(gè)變量里: 

  1. r="a b+"  
  2. [[ "a bbb" =~ $r ]]  
  3. true 

按Globbing方式的字符串比較也可以用到case語句中: 

  1. case $t in  
  2. abc*)  <action> ;;  
  3. esac 

字符串操作

Bash里有各種各樣操作字符串的方式,很多都是不可取的。

基本用戶 

  1. f="path1/path2/file.ext"  
  2. len="${#f}" # = 20 (字符串長(zhǎng)度)  
  3. # 切片操作: ${<var>:<start>} or ${<var>:<start>:<length>}  
  4. slice1="${f:6}"  
  5. # = "path2/file.ext"  
  6. slice2="${f:6:5}"  
  7. # = "path2"  
  8. slice3="${f: -8}"  
  9. # = "file.ext"(注意:"-"前有空格)  
  10. pos=6  
  11. len=5  
  12. slice4="${f:${pos}:${len}}"  
  13. # = "path2" 

替換操作(使用globbing) 

  1. f="path1/path2/file.ext"  
  2.  
  3. single_subst="${f/path?/x}"    
  4. # = "x/path2/file.ext"  
  5. global_subst="${f//path?/x}"    
  6. # = "x/x/file.ext"  
  7.  
  8. # 字符串拆分  
  9. readonly DIR_SEP="/"  
  10. array=(${f//${DIR_SEP}/ })  
  11. second_dir="${arrray[1]}"    
  12. # = path2 

刪除頭部或尾部(使用globbing) 

  1. f="path1/path2/file.ext"  
  2. # 刪除字符串頭部  
  3. extension="${f#*.}"  # = "ext"  
  4.  
  5. # 以貪婪匹配方式刪除字符串頭部  
  6. filename="${f##*/}"  # = "file.ext"  
  7.  
  8. # 刪除字符串尾部  
  9. dirname="${f%/*}"     
  10. # = "path1/path2"  
  11.  
  12. # 以貪婪匹配方式刪除字符串尾部  
  13. root="${f%%/*}"        
  14. # = "path1" 

避免使用臨時(shí)文件

有些命令需要以文件名為參數(shù),這樣一來就不能使用管道。這個(gè)時(shí)候?<()?就顯出用處了,它可以接受一個(gè)命令,并把它轉(zhuǎn)換成可以當(dāng)成文件名之類的什么東西: 

  1. # 下載并比較兩個(gè)網(wǎng)頁  
  2. diff <(wget -O - url1) <(wget -O - url2) 

還有一個(gè)非常有用處的是”here documents”,它能讓你在標(biāo)準(zhǔn)輸入上輸入多行字符串。下面的’MARKER’可以替換成任何字詞。 

  1. # 任何字詞都可以當(dāng)作分界符  
  2. command  << MARKER  
  3. ...  
  4. ${var}  
  5. $(cmd)  
  6. ...  
  7. MARKER 

如果文本里沒有內(nèi)嵌變量替換操作,你可以把***個(gè)MARKER用單引號(hào)包起來: 

  1. command << 'MARKER'  
  2. ...  
  3. no substitution is happening here.  
  4. $ (dollar sign) is passed through verbatim.  
  5. ...  
  6. MARKER 

內(nèi)置變量

提示

使用$*很少是正確的選擇。

$@能夠處理空格參數(shù),而且參數(shù)間的空格也能正確的處理。

使用$@時(shí)應(yīng)該用雙引號(hào)括起來,像”$@”這樣。

調(diào)試

對(duì)腳本進(jìn)行語法檢查: 

  1. bash -n myscript.sh 

跟蹤腳本里每個(gè)命令的執(zhí)行: 

  1. bash -v myscripts.sh 

跟蹤腳本里每個(gè)命令的執(zhí)行并附加擴(kuò)充信息: 

  1. bash -x myscript.sh 

你可以在腳本頭部使用set -o verbose和set -o xtrace來***指定-v和-o。當(dāng)在遠(yuǎn)程機(jī)器上執(zhí)行腳本時(shí),這樣做非常有用,用它來輸出遠(yuǎn)程信息。

什么時(shí)候不應(yīng)該使用bash腳本

  • 你的腳本太長(zhǎng),多達(dá)幾百行
  • 你需要比數(shù)組更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
  • 出現(xiàn)了復(fù)雜的轉(zhuǎn)義問題
  • 有太多的字符串操作
  • 不太需要調(diào)用其它程序和跟其它程序管道交互
  • 擔(dān)心性能

這個(gè)時(shí)候,你應(yīng)該考慮一種腳本語言,比如Python或Ruby。

參考

  • Advanced Bash-Scripting Guide:?http://tldp.org/LDP/abs/html/
  • Bash Reference Manual

原文鏈接:http://www.vaikan.com/bash-scripting 

責(zé)任編輯:龐桂玉 來源: 馬哥Linux運(yùn)維
相關(guān)推薦

2014-04-22 09:42:12

Bash腳本教程

2018-09-05 15:00:31

LinuxBash腳本

2017-09-20 12:44:23

LinuxBash用法及案例

2021-07-15 06:43:11

Bash調(diào)試腳本

2022-06-17 08:05:28

Grafana監(jiān)控儀表盤系統(tǒng)

2013-06-27 09:41:19

LuaLua語言Lua語言快速入門

2013-05-03 10:57:09

泛型泛型教程

2020-10-19 18:07:00

云計(jì)算技術(shù)應(yīng)用

2017-09-27 11:00:50

LinuxBash使用技巧

2019-08-01 14:35:19

Bash腳本技巧

2018-04-20 16:43:23

2011-07-11 09:58:52

2018-01-16 10:11:11

Nginx訪問日志

2016-11-16 10:29:27

LinuxVR

2015-04-21 17:35:29

代碼

2022-07-27 15:50:55

漏洞網(wǎng)絡(luò)攻擊

2013-12-19 09:20:59

2015-07-08 09:43:22

程序員

2021-03-03 11:36:57

Java 8Java 15Java

2024-11-07 16:09:53

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)