0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux Bash腳本進(jìn)階教程學(xué)習(xí)

馬哥Linux運(yùn)維 ? 來(lái)源:未知 ? 作者:李倩 ? 2018-05-01 17:45 ? 次閱讀

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

腳本安全

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

#!/bin/bashset -o nounsetset -o errexit

這樣做會(huì)避免兩種常見(jiàn)的問(wèn)題:

引用未定義的變量(缺省值為“”)

執(zhí)行失敗的命令被忽略

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

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

腳本函數(shù)

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

ExtractBashComments() { egrep "^#"}cat myscript.sh | ExtractBashComments | wccomments=$(ExtractBashComments < myscript.sh)

還有一些例子:

SumLines() { # iterating over stdin - similar to awk local sum=0 local line=”” while read line ; do sum=$((${sum} + ${line})) done echo ${sum}}SumLines < data_one_number_per_line.txtlog() { ?# classic logger ?local prefix="[$(date +%Y/%m/%d\ %H:%M:%S)]: " ?echo "${prefix} $@" >&2}log "INFO" "a message"

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

變量注解

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

local(函數(shù)內(nèi)部變量)

readonly(只讀變量)

# a useful idiom: DEFAULT_VAL can be overwritten# with an environment variable of the same namereadonly DEFAULT_VAL=${DEFAULT_VAL:-7}myfunc() {# initialize a local variable with the global default local some_var=${DEFAULT_VAL} ...}

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

x=5x=6readonly xx=7 # failure

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

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

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

# both commands below print out: A-B-C-Decho "A-`echo B-\`echo C-\\\`echo D\\\`\``"echo "A-$(echo B-$(echo C-$(echo D)))"

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

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

單中括號(hào):

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

雙中括號(hào)

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

正則表達(dá)式/Globbing

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

t="abc123"[[ "$t" == abc* ]] # true (globbing比較)[[ "$t" == "abc*" ]] # false (字面比較)[[ "$t" =~ [abc]+[123]+ ]]# true (正則表達(dá)式比較)[[ "$t" =~ "abc*" ]] # false (字面比較)

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

r="a b+"[[ "a bbb" =~ $r ]] # true

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

case $t inabc*) ;;esac

字符串操作

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

基本用戶

f="path1/path2/file.ext"len="${#f}" # = 20 (字符串長(zhǎng)度)# 切片操作: ${:} or ${::}slice1="${f:6}"# = "path2/file.ext"slice2="${f:6:5}"# = "path2"slice3="${f: -8}"# = "file.ext"(注意:"-"前有空格)pos=6len=5slice4="${f:${pos}:${len}}"# = "path2"

替換操作(使用globbing)

f="path1/path2/file.ext"single_subst="${f/path?/x}" # = "x/path2/file.ext"global_subst="${f//path?/x}" # = "x/x/file.ext"# 字符串拆分readonly DIR_SEP="/"array=(${f//${DIR_SEP}/ })second_dir="${arrray[1]}" # = path2

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

f="path1/path2/file.ext"# 刪除字符串頭部extension="${f#*.}" # = "ext"# 以貪婪匹配方式刪除字符串頭部filename="${f##*/}" # = "file.ext"# 刪除字符串尾部dirname="${f%/*}" # = "path1/path2"# 以貪婪匹配方式刪除字符串尾部root="${f%%/*}" # = "path1"

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

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

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

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

# 任何字詞都可以當(dāng)作分界符command << MARKER...${var}$(cmd)...MARKER

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

command << 'MARKER'...no substitution is happening here.$ (dollar sign) is passed through verbatim....MARKER

內(nèi)置變量

提示

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

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

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

調(diào)試

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

bash -n myscript.sh

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

bash -v myscripts.sh

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

bash -x myscript.sh

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

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

你的腳本太長(zhǎng),多達(dá)幾百行

你需要比數(shù)組更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)

出現(xiàn)了復(fù)雜的轉(zhuǎn)義問(wèn)題

有太多的字符串操作

不太需要調(diào)用其它程序和跟其它程序管道交互

擔(dān)心性能

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

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209476
  • 腳本
    +關(guān)注

    關(guān)注

    1

    文章

    389

    瀏覽量

    14864

原文標(biāo)題:Linux Bash腳本15分鐘進(jìn)階教程

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【shell腳本進(jìn)階】幾個(gè)常用的shell進(jìn)階腳本

    【shell腳本進(jìn)階】幾個(gè)常用的shell進(jìn)階腳本
    的頭像 發(fā)表于 09-19 08:59 ?1892次閱讀
    【shell<b class='flag-5'>腳本</b><b class='flag-5'>進(jìn)階</b>】幾個(gè)常用的shell<b class='flag-5'>進(jìn)階</b><b class='flag-5'>腳本</b>

    開(kāi)發(fā)人員必須具備的Bash腳本知識(shí)

    您可以使用 Bash 腳本自動(dòng)執(zhí)行各種任務(wù)。掌握基礎(chǔ)知識(shí)并開(kāi)始您的 Bash 腳本之旅。
    發(fā)表于 09-27 09:09 ?428次閱讀

    bash腳本中的test命令詳解

    bash 腳本中的 test? 命令用于檢查表達(dá)式的有效性,檢查命令或表達(dá)式為 true 或者 false。此外,它還可以用于檢查文件的類型和權(quán)限。
    發(fā)表于 11-24 15:32 ?3780次閱讀
    <b class='flag-5'>bash</b><b class='flag-5'>腳本</b>中的test命令詳解

    如何在bash shell腳本中使用變量

    如果你使用編程語(yǔ)言編寫過(guò)程序,那么一定接觸過(guò)變量。而在 bash 腳本的編寫時(shí),變量也是一個(gè)很重要的概念。今天我們分享一下如何在 bash 腳本中使用變量。
    發(fā)表于 12-02 16:32 ?2111次閱讀
    如何在<b class='flag-5'>bash</b> shell<b class='flag-5'>腳本</b>中使用變量

    Linux_Bash腳本編程大全

    毫無(wú)疑問(wèn),UNIX/Linux 最重要的軟件之一就是shell,目前最流行的shell 被稱為Bash(Bourne Again Shell),幾乎所有的Linux 和絕大部分的UNIX 都可以使用
    發(fā)表于 10-22 16:17 ?57次下載

    高級(jí)Bash 腳本編程指南

    高級(jí)Bash 腳本編程指南
    發(fā)表于 10-26 08:33 ?7次下載
    高級(jí)<b class='flag-5'>Bash</b> <b class='flag-5'>腳本</b>編程指南

    命令行重度用戶需要的實(shí)用BASH腳本

    今天,我偶然發(fā)現(xiàn)了一組適用于命令行重度用戶的實(shí)用 BASH 腳本,這些腳本被稱為 Bash-Snippets,它們對(duì)于那些整天都與終端打交道的人來(lái)說(shuō)可能會(huì)很有幫助。
    的頭像 發(fā)表于 08-30 10:37 ?2610次閱讀

    虛擬機(jī):Bash Shell腳本打印出執(zhí)行的命令

    默認(rèn)情況下,bash腳本不會(huì)打印執(zhí)行的每個(gè)命令,這個(gè)有時(shí)候不太方面。
    的頭像 發(fā)表于 06-22 14:44 ?4557次閱讀

    Raspberry Pi Bash Shell 腳本簡(jiǎn)介

      拋開(kāi)潛在的麻煩不談,Bash 可以是一個(gè)非常強(qiáng)大的工具,讓您可以自動(dòng)執(zhí)行各種任務(wù)。在即將發(fā)表的文章中,我將展示如何使用 Bash 腳本以及一些硬件技巧來(lái)自動(dòng)化我的 Raspberry Pi 冷卻風(fēng)扇。
    的頭像 發(fā)表于 08-15 15:08 ?1198次閱讀
    Raspberry Pi <b class='flag-5'>Bash</b> Shell <b class='flag-5'>腳本</b>簡(jiǎn)介

    如何在bash shell腳本中接受參數(shù)

    終端命令通常包含一些參數(shù),在使用的時(shí)候可以提供不同的參數(shù)來(lái)確定命令的執(zhí)行方式。POSIX規(guī)范中包含了用于命令行接口的選項(xiàng)。這也是與最早的UNIX應(yīng)用程序建立的一個(gè)由來(lái)已久的約定,所以當(dāng)你在寫bash腳本的時(shí)候,需要知道如何在腳本
    的頭像 發(fā)表于 12-09 17:34 ?2712次閱讀

    bash腳本中的循環(huán)功能

    循環(huán)是 bash 腳本中一個(gè)很重要的功能,用途廣泛。本篇文章我們介紹三種不同的循環(huán),然后利用循環(huán)遍歷數(shù)組。
    的頭像 發(fā)表于 12-14 17:30 ?3611次閱讀

    如何用10行bash shell腳本監(jiān)控Linux

    監(jiān)控我們的環(huán)境對(duì)于服務(wù)器運(yùn)維來(lái)說(shuō)至關(guān)重要,尤其是在部署新的應(yīng)用程序時(shí)。如今,公司每天都使用開(kāi)源解決方案來(lái)監(jiān)控系統(tǒng)資源。但是,當(dāng)出于測(cè)試的目的來(lái)監(jiān)控一定時(shí)間時(shí),bash 腳本會(huì)派上用場(chǎng)。
    的頭像 發(fā)表于 04-10 11:50 ?734次閱讀

    Bash腳本中特殊變量$0是什么?

    Bash 腳本中,`$0` 是一個(gè)特殊變量,它代表當(dāng)前腳本的路徑和名稱。這個(gè)變量用于表示腳本自身,它是 Bash 環(huán)境中的一個(gè)重要組成部
    的頭像 發(fā)表于 05-12 14:41 ?1846次閱讀

    BASH shell腳本篇—函數(shù)

    函數(shù)是代碼重用的最重要方式。Bash函數(shù)可以定義為一組命令,在bash腳本中多次調(diào)用。
    的頭像 發(fā)表于 10-20 16:31 ?1104次閱讀

    BASH shell腳本篇—文件處理介紹

    Bash Shell腳本中,可以使用多種方法來(lái)對(duì)文件進(jìn)行操作,包括讀取文件或?qū)懭胛募?/div>
    的頭像 發(fā)表于 10-23 16:51 ?629次閱讀