shell從入門到放棄-優雅編程(1)

shell從入門到放棄-優雅編程(1)

0x00 前言

小K本着「能坐着毫不站着,能躺着毫不坐着」的「懶人之道」,努力打造規範和可靠的代碼。下面就給你們講講小k在學習和使用shell過程當中遇到的問題。shell

0x01 指令異常判斷

今天真高興啊,今天真興高,小K一個小時就完成了今天的代碼開發。小Q,來給我測試一下,立刻就能上線。編程

#!/bin/bash
echo '先將原數據文件a.txt作個備份'
cp a.txt bak.txt
echo '將原文件裏的xx替換成yy'
sed -i "s/xxx/yyy/g" a.txt
###balabala省略一堆指令
echo '成功'

小Q:嘿嘿,來啦。無論三七二十一,先來個異常場景:a.txt不存在。bash

執行日誌以下:函數

先將原數據文件a.txt作個備份
cp: a.txt: No such file or directory
將原文件裏的xx替換成yy
sed: 1: "a.txt": command a expects \ followed by text
成功

小Q:小K啊,代碼都報異常了,最後告訴我成功。。。學習

小K:簡單,我經過$?的值來判斷上一步的狀態進而決定是繼續執行仍是異常退出。(哼哼,爲了防止小Q在找茬兒,我每一個都加判斷)測試

echo '先將原數據文件a.txt作個備份'
cp a.txt bak.txt
if [ $? -ne 0 ];then
    echo 'command fail'
    exit 1
fi
echo '將原文件裏的xx替換成yy'
sed -i "s/xxx/yyy/g" a.txt
if [ $? -ne 0 ];then
    echo 'command fail'
    exit 1
fi
###balabala一堆邏輯代碼
echo '成功'

一頓操做猛如虎,原來10行的代碼活生生變成了40行,有沒有簡單的方式呢?(幸好公司不是拿代碼行數作KPI,要否則我能寫到公司破產)優化

 

那有什麼方式能夠優化一下呢?噔噔噔噔...答案就是:set -o errexitspa

set -o errexit

echo '先將原數據文件a.txt作個備份'
cp a.txt bak.txt
echo '將原文件裏的xx替換成yy'
sed -i "s/xxx/yyy/g" a.txt
###balabala一堆邏輯代碼
echo '成功'

Tips:日誌

  1. 一旦有任何一個指令返回非0值,則異常退出,此時$?將不起做用
  2. 若是須要程序出錯也繼續執行,能夠在執行命令前加if判斷或者在命令上追加「 || true」

0x02 函數化

小K做爲努力「糞」發向上的有爲「青年」,把日誌打成這樣實在是讓人看不下去,至少得加個時間戳吧。blog

這個不難,經過date就行,但這一行一行的替換着實不像我這個懶人的風格。

立刻中午了,被小Q折騰的連水都沒喝一口,直接上代碼:

#具體格式能夠自行定義,這裏以 時間 日誌級別 日誌信息展現
function logger() {
    echo $(date "+%Y-%m-%d %H:%M:%S")" $1:$2"
}

logger 'info' '先將原數據文件a.txt作個備份'
cp a.txt bak.txt

Tips:

  1. 公用代碼,業務邏輯均可以封裝到函數。簡單明瞭,可讀性強。

0x03 參數傳遞

小P:小K,小Q來一下。我忽然想到原數據文件可能不叫a.txt,我又不想改文件名。大家給搞下。

小K:(又改需求,一臉黑線。。。) 那我加個外部參數傳遞吧: sh xxx.sh a.txt

source=$1
logger 'info' "先將原數據文件[${source}]作個備份"
cp ${source} bak.txt

小Q:若是後面還要加功能,須要傳入多個參數呢?

小K:嗯。。。使用$1的方式,代碼裏確定還得須要定義多個變量,有點刷代碼行數的嫌疑,並且若是不當心傳錯位很差判斷。

這樣的話小K就只能出殺手鐗了:sh xxx.sh source=a.txt target=bak.txt

for i in $*
do
    export $i
done
logger 'info' "將原數據文件[${source}]複製到[${target}]"
cp ${source} ${target}

Tips:

  1. 能夠經過循環的方式和export直接將外部參數賦值給變量

0x04 變量未定義

哼哼哈hi,搞定。等等,萬一小Q又來個異常測試,不給我傳變量名可咋整?

能夠在代碼里加上set –o nounset。

for i in $*
do
    export $i
done
set -o nounset

logger 'info' "將原數據文件[${source}]複製到[${target}]"
cp ${source} ${target}

Tips:

  1. 當使用未定義的變量時,設置set -o nounset 可讓程序強制退出。老闆不再用擔憂rm -rf /${xxx}

這些小技巧你學會了嗎?

I will be back!

 


做者:範令凱

公衆號:互聯網技術到家

頭條號:互聯網技術到家

互聯網技術到家

相關文章
相關標籤/搜索