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!

 


做者:范令凯

公众号:互联网技术到家

头条号:互联网技术到家

互联网技术到家

相关文章
相关标签/搜索