色偷偷91综合久久噜噜-色偷偷成人-色偷偷尼玛图亚洲综合-色偷偷人人澡久久天天-国内精品视频一区-国内精品视频一区二区三区

Hello! 歡迎來(lái)到小浪云!


第二節(jié):Bash編程易犯的錯(cuò)誤


第二節(jié):Bash編程易犯的錯(cuò)誤

上一篇文章參見(jiàn) 第一節(jié):bash編程易犯的錯(cuò)誤。

13. cat file | sed s/foo/bar/ > file

你不應(yīng)該在一個(gè)管道中,從一個(gè)文件讀的同時(shí),再往相同的文件里面寫(xiě),這樣的后果是未知的。

你可以為此創(chuàng)建一個(gè)臨時(shí)文件,這種做法比較安全可靠:

 # sed 's/foo/bar/g' file > tmpfile && mv tmpfile file 

或者,如果你用得是 gnu Sed 4.x 以上的版本,可以使用-i 選項(xiàng)即時(shí)修改文件的內(nèi)容:

 # sed -i 's/foo/bar/g' file 

14. echo $foo

這種看似無(wú)害的命令往往會(huì)給初學(xué)者千萬(wàn)極大的困擾,他們會(huì)懷疑是不是因?yàn)?$foo 變量的值是錯(cuò)誤的。事實(shí)卻是因?yàn)椋?foo 變量在這里沒(méi)有使用雙引號(hào),所以在解析的時(shí)候會(huì)進(jìn)行單詞拆分和文件名展開(kāi),最終導(dǎo)致執(zhí)行結(jié)果與預(yù)期大相徑庭:

 msg="Please enter a file name of the form *.zip" echo $msg 

這里整句話會(huì)被拆分成單詞,然后其中的通配符會(huì)被展開(kāi),例如*.zip。當(dāng)你的用戶(hù)看到如下的結(jié)果時(shí),他們會(huì)怎樣想:

  Please enter a file name of the form freenfss.zip lw35nfss.zip  再舉一個(gè)例子(假設(shè)當(dāng)前目錄下有以 .zip 結(jié)尾的文件):  var="*.zip"   # var 包括一個(gè)星號(hào),一個(gè)點(diǎn)號(hào)和 zip echo "$var"   # 輸出 *.zip echo $var     # 輸出所有以 .zip 結(jié)尾的文件 

實(shí)際上,這里使用 echo 命令并不是絕對(duì)的安全。例如,當(dāng)變量的值包含-n時(shí),echo 會(huì)認(rèn)為它是一個(gè)合法的選項(xiàng)而不是要輸出的內(nèi)容(當(dāng)然如果你能夠保證不會(huì)有-n 這種值,可以放心地使用 echo 命令)。

完全可靠的打印變量值的方法是使用 printf

 printf "%s " "$foo" 

15. $foo=bar

略過(guò)

16. foo = bar

當(dāng)賦值時(shí),等號(hào)兩邊是不允許出現(xiàn)空格的,這同 C 語(yǔ)言不一樣。當(dāng)你寫(xiě)下 foo = bar 時(shí),Shell 會(huì)將該命令解析成三個(gè)單詞,然后第一個(gè)單詞 foo 會(huì)被認(rèn)為是一個(gè)命令,后面的內(nèi)容會(huì)被當(dāng)作命令參數(shù)。

同樣地,下面的寫(xiě)法也是錯(cuò)誤的:

 foo= bar    # WRONG! foo =bar    # WRONG! $foo = bar; # COMPLETELY WRONG! 

正確的寫(xiě)法應(yīng)該是這樣的:

 foo=bar     # Right. foo="bar"   # more Right. 

17. echo 或者可以使用雙引號(hào),它也可以跨越多行,而且因?yàn)?echo 命令是內(nèi)置命令,相同情況下它會(huì)更加高效:

 echo "Hello world How's it going?" 

18. su -c ‘some command’

這種寫(xiě)法“幾乎”是正確的。問(wèn)題是,在許多平臺(tái)上,su 支持 -c 參數(shù),但是它不一定是你認(rèn)為的。比如,在 OpenBSD 平臺(tái)上你這樣執(zhí)行會(huì)出錯(cuò):

 $ su -c 'echo hello' su: only the superuser may specify a login class  在這里,-c是用于指定login-class。如果你想要傳遞 -c 'some command' 給 shell,最好在之前顯示地指定 username:  $ su root -c 'some command' # Now it's right. 

19. cd /foo; bar

如果你不檢查 cd 命令執(zhí)行是否成功,你可以會(huì)在錯(cuò)誤的目錄下執(zhí)行 bar 命令,這有可能會(huì)帶來(lái)災(zāi)難,比如 bar 命令是 rm -rf *。

你必須經(jīng)常檢查 cd 命令執(zhí)行是否有錯(cuò)誤,簡(jiǎn)單的做法是:

 cd /foo && bar  如果在 cd 命令后有多個(gè)命令,你可以選擇這樣寫(xiě):  cd /foo || exit 1 bar baz bat ... # Lots of commands. 

出錯(cuò)時(shí),cd 命令會(huì)報(bào)告無(wú)法改變當(dāng)前目錄,同時(shí)將錯(cuò)誤消息輸出到標(biāo)準(zhǔn)錯(cuò)誤,例如”bash: cd: /foo: No such file or directory”。如果你想要在標(biāo)準(zhǔn)輸出同時(shí)輸出自定義的錯(cuò)誤提示,可以使用復(fù)合命令(command grouping):

 cd /net || { echo "Can't read /net. make sure you've logged in to the Samba network, and try again."; exit 1; } do_stuff more_stuff 

注意,在{號(hào)和 echo 之間需要有一個(gè)空格,同時(shí)}之前要加上分號(hào)。

順便提一下,如果你要在腳本里頻繁改變當(dāng)前目錄,可以看看 pushd/popd/dirs 等命令,可能你在代碼里面寫(xiě)的 cd/pwd 命令都是沒(méi)有必要的。

說(shuō)到這,比較下下面兩種寫(xiě)法:

 find ... -type d -print0 | while IFS= read -r -d '' subdir; do    here=$PWD    cd "$subdir" && whatever && ...    cd "$here" done find ... -type d -print0 | while IFS= read -r -d '' subdir; do    (cd "$subdir" || exit; whatever; ...) done 

下面的寫(xiě)法,在循環(huán)fork 了一個(gè)子 shell 進(jìn)程,子 shell 進(jìn)程中的 cd 命令僅會(huì)影響當(dāng)前 shell的環(huán)境變量,所以父進(jìn)程中的環(huán)境命令不會(huì)被改變;當(dāng)執(zhí)行到下一次循環(huán)時(shí),無(wú)論之前的 cd 命令有沒(méi)有執(zhí)行成功,我們會(huì)回到相同的當(dāng)前目錄。這種寫(xiě)法相較前面的用法,代碼更加干凈。

20. [ bar == “$foo” ]

正確的用法:

 [ bar = "$foo" ] && echo yes [[ bar == $foo ]] && echo yes 

21. for i in {1..10}; do ./something &; done

你不應(yīng)該在&后面添加分號(hào),刪除它:

 for i in {1..10}; do ./something & done  或者改成多行的形式:  for i in {1..10}; do     ./something & done 

&和分號(hào)一樣也可以用作命令終止符,所以你不要將兩個(gè)混用到一起。一般情況下,分號(hào)可以被換行符替換,但是不是所有的換行符都可以用分號(hào)替換。

22. cmd1 && cmd2 || cmd3

有些人喜歡把&&和||作為if…then…else…fi 的簡(jiǎn)寫(xiě)語(yǔ)法,在多數(shù)情況下,這種寫(xiě)法沒(méi)有問(wèn)題。例如:

 [[ -s $errorlog ]] && echo "Uh oh, there were some errors." || echo "Successful." 

但是,這種結(jié)構(gòu)并不是在所有情況下都完全等價(jià)于 if…fi 語(yǔ)法。這是因?yàn)樵?amp;&后面的命令執(zhí)行結(jié)束時(shí)也會(huì)生成一個(gè)返回碼,如果該返回碼不是真值(0代表 true),||后面的命令也會(huì)執(zhí)行,例如:

 i=0 true && ((i++)) || ((i--)) echo $i # 輸出 0 

看起來(lái)上面的結(jié)果應(yīng)該是返回1,但是結(jié)果卻是輸出0,為什么呢?原因是這里 i++ 和 i– 都執(zhí)行了一遍。

其中,((i++))命令執(zhí)行算術(shù)運(yùn)算,表達(dá)式計(jì)算的結(jié)果為0。這里和 C 語(yǔ)言一樣,表達(dá)式的結(jié)果為0被認(rèn)為是 false。所以當(dāng) i=0 的時(shí)候,((i++))命令執(zhí)行的返回碼為1(false),從而會(huì)執(zhí)行接下來(lái)的((i–))命令。

如果我們?cè)谶@里使用前綴自增運(yùn)算符的話,返回的結(jié)果恰恰為1,因?yàn)?(++i))執(zhí)行的返回碼是0(true):

 i=0 true && (( ++i )) || (( --i )) echo $i # Prints 1 

不過(guò)在你無(wú)法保證 y 的執(zhí)行結(jié)果是,絕對(duì)不要依靠 x && y || z這種寫(xiě)法。上面這種巧合,在 i 初始化為-1時(shí)也會(huì)有問(wèn)題。

如果你喜歡代碼更加安全健壯,建議使用 if…fi 語(yǔ)法:

 i=0 if true; then    ((i++)) else    ((i--)) fi  echo $i # 輸出 1 

23. echo “Hello World!”

在交互式的 Shell 環(huán)境下,你執(zhí)行以上命令會(huì)遇到下面的錯(cuò)誤:

 bash: !": event not found  這是因?yàn)椋谀J(rèn)的交互式 Shell 環(huán)境下,Bash 發(fā)現(xiàn)感嘆號(hào)時(shí)會(huì)執(zhí)行歷史命令展開(kāi)。在 Shell 腳本中,這種行為是被禁止的,所以不會(huì)發(fā)生錯(cuò)誤。  不幸地是,你認(rèn)為明顯正確地修復(fù)方法,也不能工作,你會(huì)發(fā)現(xiàn)反斜杠并沒(méi)有轉(zhuǎn)義感嘆號(hào):  # echo "hi!" hi!  最簡(jiǎn)單地方法是禁用 histexpand 選項(xiàng),你可以通過(guò) set +H 或者 set +o histexpand 命令來(lái)完成。  下面四種寫(xiě)法都可以解決:  # 1. 使用單引號(hào)  echo 'Hello World!'  # 2. 禁用 histexpand 選項(xiàng)  set +H echo "Hello World!"  # 3. 重置 histchars  histchars=  # 4. 控制 shell 展開(kāi)的順序,命令行歷史展開(kāi)是在單詞拆分之前執(zhí)行的  # 參見(jiàn):Bash man 手冊(cè)的History Expansion一節(jié)  exmark='!'  echo "Hello, world$exmark"  

由于篇幅限制,本系列文章會(huì)分成多篇文章,下一篇參見(jiàn)第節(jié):Bash編程易犯的錯(cuò)誤。

相關(guān)閱讀

主站蜘蛛池模板: 亚洲欧美综合国产精品一区 | 久久久精品国产免费观看同学 | 国产微拍一区二区三区四区 | 亚洲狠狠 | 精品国产一区二区三区2021 | www.亚洲成人 | 久久激情网 | 色噜噜狠狠大色综合 | 久久99国产精品久久99果冻传媒 | 可以看黄色小说的软件 | 人人爱天天操 | 九九色综合| 操日日| 国产天天射| 色香天天| 极品美女一级毛片 | 天天毛片| 久久久国产精品四虎 | 精品四虎免费观看国产高清午夜 | 国内精品免费一区二区观看 | 成人欧美一区二区三区黑人3p | 三级在线网站 | 国产精品欧美日韩一区二区 | 久久亚洲精品tv | 激情开心成人网 | 久久伊人中文字幕麻豆 | 亚洲精品社区 | 色一欲一性一乱一区二区三区 | 黄色片网站在线播放 | 激情六月综合 | 国产一区二区精品久 | 国产一级做a爰片在线 | 色综合中文 | a级片网站| 中日欧洲精品视频在线 | 国内精品区一区二区三 | 玖玖国产 | 欧美一级日韩 | 久久在精品线影院精品国产 | 亚洲欧美日韩精品久久 | 精品国产高清在线看国产 |