shell grep 变量_老司机给出的关于 shell 脚本的8个建议,必收!

f2d135736ab8327e816003caca05dd07.png

这八个建议,来源于键者几年来编写 shell 脚本的一些经验和教训。事实上开始写的时候还不止这几条,后来思索再三,去掉几条无关痛痒的,最后剩下八条。毫不夸张地说,每条都是精挑细选的,虽然有几点算是老生常谈了。

1

指定bash

shell 脚本的第一行,#!之后应该是什么?

如果拿这个问题去问别人,不同的人的回答可能各不相同。我见过/usr/bin/env bash,也见过/bin/bash,还有/usr/bin/bash,还有/bin/sh,还有/usr/bin/env sh。这算是编程界的“’茴’字四种写法”了。

在多数情况下,以上五种写法都是等价的。但是,写过程序的人都知道:“少数情况”里往往隐藏着意想不到的坑。

如果系统的默认 shell 不是 bash 怎么办?比如某 Linux 发行版的某个版本,默认的 sh 就不是 bash。

如果系统的 bash 不是在 /usr/bin/bash 怎么办?

我推荐使用 /usr/bin/env bash 和 /bin/bash。前者通过env添加一个中间层,让env在$PATH中搜索bash;后者则是官方背书的,约定俗成的 bash 位置,/usr/bin/bash不过是指向它的一个符号链接。

2

set -e 和 set -x

OK,经过一番讨论,现在第一行定下来了。接下来该开始写第二行了吧?

且慢!在你开始构思并写下具体的代码逻辑之前,先插入一行set -e和一行set -x。

set -x会在执行每一行 shell 脚本时,把执行的内容输出来。它可以让你看到当前执行的情况,里面涉及的变量也会被替换成实际的值。

set -e会在执行出错时结束程序,就像其他语言中的“抛出异常”一样。(准确说,不是所有出错的时候都会结束程序,见下面的注)

注:set -e结束程序的条件比较复杂,在man bash里面,足足用了一段话描述各种情景。大多数执行都会在出错时退出,除非 shell 命令位于以下情况:

一个 pipeline 的非结尾部分,比如 error | ok

一个组合语句的非结尾部分,比如 ok && error || other

一连串语句的非结尾部分,比如 error; ok

位于判断语句内,包括 test、if、 while 等等。

这两个组合在一起用,可以在 debug 的时候替你节省许多时间。出于防御性编程的考虑,有必要在写第一行具体的代码之前就插入它们。扪心自问,写代码的时候能够一次写对的次数有多少?大多数代码,在提交之前,通常都经历过反复调试修改的过程。与其在焦头烂额之际才引入这两个配置,不如一开始就给 debug 留下余地。在代码终于可以提交之后,再考虑是否保留它们也不迟。

3

带上shellcheck

好了,现在我已经有了三行(样板)代码,具体的业务逻辑一行都没写呢。是不是该开始写了?

且慢!工欲善其事,必先利其器。这次,我就介绍一个 shell 脚本编写神器:shellcheck

说来惭愧,虽然写了几年 shell 脚本,有些语法我还是记不清楚。这时候就要依仗 shellcheck 指点一下了。

shellcheck 除了可以提醒语法问题以外,还能检查出 shell 脚本编写常见的 bad code。本来我的N条建议里面,还有几条是关于这些 bad code 的,不过考虑到 shellcheck 完全可以发掘出这些问题,于是忍痛把它们都剔除在外了。毫无疑问,使用 shellcheck 给我的 shell 编写技能带来了巨大的飞跃。

所谓“站在巨人的肩膀上”,虽然我们这些新兵蛋子,技能不如老兵们强,但是我们可以在装备上赶上对方啊!动动手安装一下,就能结识一个循循善诱的“老师”,何乐而不为?

顺便一提,shellcheck 居然是用 haskell 写的。谁说 haskell 只能用来装逼?

4

变量展开

在 shell 脚本中,偶尔可以看到这样的做法:echo $xxx | awk/sed/grep/cut...。看起来大张形势的样子,其实不过是想修改一个变量的值。

杀鸡何必用牛刀?bash 内建的变量展开机制已经足以满足你各种需求!还是老方法, read the f**k manaul! man bash 然后搜索Parameter Expansion,下面就是你想要的技巧。键者也写过一篇相关的文章,希望能助上一臂之力:玩转 Bash变量。

5

注意local

随着代码越写越多,你开始把重复的逻辑提炼成函数。有可能你会掉到 bash 的一个坑里。在 bash,如果不加 local 限定词,变量默认都是全局的。变量默认全局——这跟 js 和 lua 相似;但相较而言,很少有 bash 教程一开始就告知你这个事实。在顶级作用域里,是否是全局变量并不重要。但是在函数里面,声明一个全局变量可能会污染到其他作用域(尤其在你根本没有注意到这一点的情况下)。所以,对于在函数内声明的变量,请务必记得加上 local 限定词。

6

trap 信号

如果你写过稍微复杂点的在后台运行的程序,应该知道 posix 标准里面“信号”是什么一回事。如果不知道,直接看下一段。像其他语言一样,shell 也支持处理信号。trap sighandler INT可以在接收到 SIGINT 时调用 sighandler 函数。捕获其他信号的方式以此类推。

不过 trap 的主要应用场景可不是捕获哪个信号。trap 命令支持“捕获”许多不同的流程——准确来说,允许用户给特定的流程注入函数调用。其中最为常用的是trap func EXIT和trap func ERR。

trap func EXIT允许在脚本结束时调用函数。由于无论正常退出抑或异常退出,所注册的函数都能得以调用,在需要调用一个清理函数的场景下,我都是用它注册清理函数,而不是简单地在脚本结尾调用清理函数。

trap func ERR允许在运行出错时调用函数。一个常用的技法是,使用全局变量ERROR存储错误信息,然后在注册的函数中根据存储的值完成对应的错误报告。把原本四分五裂的错误处理逻辑集中到一处,有时候会起奇效。不过要记住,程序异常退出时,既会调用EXIT注册的函数,也会调用ERR注册的函数。

7

三思后行

以上几条都是具体的建议,剩下两条比较务虚。

这条建议的名字叫“三思而行”。其实无论写什么代码,哪怕只是一个辅助脚本,都要三思而行,切忌粗心大意。不,写脚本的时候更要记住这点。毕竟许多时候,一个复杂的脚本发端于几行小小的命令。一开始写这个脚本的人,也许以为它只是一次性任务。代码里难免对一些外部条件有些假定,在当时也许是正常的,但是随着外部环境的变化,这些就成了隐藏的暗礁。雪上加霜的是,几乎没有人会给脚本做测试。除非你去运行它,否则不知道它是否还能正常使用。

要想减缓脚本代码的腐烂速度,需要在编写的时候辨清哪些是会变的依赖、哪些是脚本正常运行所不可或缺的。要有适当的抽象,编写可变更的代码;同时要有防御性编程的意识,给自己的代码一道护城河。

8

扬长避短

有些时候,使用 shell 写脚本就意味着难以移植、难以统一地进行错误处理、难以利索地处理数据。

虽然使用外部的命令可以方便快捷地实现各种复杂的功能,但作为硬币的反面,不得不依靠grep、sed、awk等各种工具把它们粘合在一起。

如果有兼容多平台的需求,还得小心规避诸如BSD和GNU coreutils,bash版本差异之类奇奇怪怪的陷阱。

由于缺乏完善的数据结构以及一致的API,shell 脚本在处理复杂的逻辑上力不从心。

解决特定的问题要用合适的工具。知道什么时候用 shell,什么时候切换到另外一门更通用的脚本语言(比如ruby/python/perl),这也是编写可靠 shell 脚本的诀窍。如果你的任务可以组合常见的命令来完成,而且只涉及简单的数据,那么 shell 脚本就是适合的锤子。如果你的任务包含较为复杂的逻辑,而且数据结构复杂,那么你需要用 ruby/python 之类的语言编写脚本。

3月云计算在线免费训练营开讲啦5天技术免费学扫码预约抢名额

 

c00899d0ac5404420f3a86fbd42c17a5.png

如有疑问,速寻达妹微信:zdzc3087880280;达妹QQ:3535503962。

精彩推荐:

  • 达内教育面向全国用户提供免费课程!(文中申请)

  • 都在"云"上,你说云运维会吃香不?

  • 运维的新“加码”技能—Python!

  • 2019年达内学员入职中国软件百强榜!完整榜单!

dffa59f28fb3573a0bfc5b3c20bfd77b.png

8f3c1d0683035173d7d624d34e5362ca.gif点击“

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不是说好一起长大的吗?

1 仿佛闻到了嫉妒的味道!2 阿拉:不是说好一起长大的吗?3 还有这么小的菠萝蜜??4 你以为它是个橘子其实它并不是5 当我吃到自己喜欢吃的东西时……6 以后吃完小龙虾,千万别扔,有妙用7 这是啥玩意…

javascript:设置URL参数的方法,适合多条件查询

适用场景&#xff1a;多条件查询情况&#xff0c;如下图所示&#xff1a; 通过设置URL参数&#xff0c;再结合数据源控件设置的RUL参数&#xff0c;就能进行简单的多条件查询了。 javascript函数&#xff1a; <mce:script type"text/javascript"><!-- //设置…

SQL点滴19—T-SQL中的透视和逆透视

原文:SQL点滴19—T-SQL中的透视和逆透视透视 今天抽一点时间来看看透视和逆透视语句&#xff0c;简单的说就是行列转换。假设一个销售表中存放着产品号&#xff0c;产品折扣&#xff0c;产品价格三个列&#xff0c;每一种产品号可能有多种折扣&#xff0c;每一种折扣只对应一个…

Magicodes.IE 2.5.5.3发布

2.5.5.32021.08.27修复Append方式导出多个sheet时&#xff0c;发生“Tablename is not unique”错误&#xff0c;具体见#299。2.5.5.22021.08.24添加对Abp模块的包装&#xff0c;具体见#318。Magicodes.IE.Excel.Abp&#xff08;MagicodesIEExcelModule&#xff09;注册IExcelE…

C语言阿斯码,木叶四位上忍设定各不相同,网红负责秀操作,她只需要美就够了...

原标题&#xff1a;木叶四位上忍设定各不相同&#xff0c;网红负责秀操作&#xff0c;她只需要美就够了木叶四位上忍设定各不相同&#xff0c;网红负责秀操作&#xff0c;她只需要美就够了说道忍界网红&#xff0c;那一定就是卡卡西了。卡卡西在《火影》当中的表现俘获了大批小…

80岁COBOL码农:扶我起来,这个bug我会修!

95&#xff05;的 ATM 交易通过 COBOL 程序&#xff0c;80&#xff05;的现场交易依赖于它们&#xff0c;超过 40&#xff05;的银行仍然使用 COBOL 作为其系统的基础。由于年轻人懂 COBOL 的比较少&#xff0c;美国康涅狄格州劳工部正在召回经验丰富的退休 COBOL 人员。来源&a…

小心使用宏

开发过程中&#xff0c;会经常使用宏定义&#xff0c;偶尔还会碰到重复定义的宏&#xff0c;有些时候会造成不良影响。 见如下例子&#xff1a; Test.h #ifndef GUARD_TEST_H #define GUARD_TEST_H class CTest { public: CTest(); virtual ~CTest(); void Display(void); publ…

数据资产纳入国资保值增值考核

首先是国资云近期横空出世&#xff0c;国资云的推广预示着党政及国企未来将坚持私有云技术路线。从天津、四川等省市国资云平台的建设方式来看&#xff0c;未来党政及国企部门的业务系统上云将坚持私有云的技术路线&#xff0c;由此可能对未来国内云计算市场带来深远影响。国资…

iPhone5:4G是否进入主流的风向标?

当业内的目光不约而同地集中到苹果即将发布的iPad2的时候&#xff0c;按照惯例&#xff0c;苹果的另一款重量级产品iPhone5也会在今年登场。近日&#xff0c;国外有预测称&#xff0c;苹果的iPhone5可能会不支持 4G网络&#xff0c;这多少令业内感到意外和失望&#xff0c;并由…

一滴水从高处落下来,会不会砸死人?

全世界只有3.14 % 的人关注了爆炸吧知识有一个相当古老的段子是这么说的&#xff1a;为了涨姿势&#xff0c;我加入一个物理博士群&#xff0c;见到有人问&#xff1a;一滴水从很高的地方落下来&#xff0c;会不会弄死人&#xff1f;群里一下就热闹起来&#xff0c;各种公式&am…

给ubuntu换个图标主题(icon theme)

2019独角兽企业重金招聘Python工程师标准>>> 对于linux mint&#xff0c; http://linuxmint-art.org/?xcontentmode8325给出了很多icon主题。 安装方法有下面几种&#xff1a; 1、使用PPA 2、将解压后的icon主题目录放到 /usr/share/icons目录下。 3、将解压后的i…

贴图程序进展

从2.28号到现在&#xff0c;在休息&#xff0c;在此先整理下之前的情况&#xff0c;对问题和要做的内容进行一下梳理。 首先&#xff0c;把之前的问题稍做下总结&#xff0c;上次提到OpenGL版本这块&#xff0c;我的是1.1版本&#xff0c;所以就只能用顶点数组来实现了&#xf…

get到一个生气后的牵手方式!太可爱了

1 公司新聘的出纳&#xff0c;大家看看尽不尽职&#xff1f;2 柯基&#xff1a;腿长有啥用啊3 男友力爆表的小螃蟹4 一滴水的下落&#xff0c;原来如此有条有理5 内容太过真实6 get到一个生气后的牵手方式7 你们那里的这条街叫什么&#xff1f;你点的每个赞&#xff0c;我都认真…

python flask框架是什么_Flask框架是什么?带你安装运行第一个Flask程序

1 了解框架 Flask作为Web框架&#xff0c;它的作用主要是为了开发Web应用程序。那么我们首先来了解下Web应用程序。Web应用程序 (World Wide Web)诞生最初的目的&#xff0c;是为了利用互联网交流工作文档。 1.1 一切从客户端发起请求开始。 所有Flask程序都必须创建一个程序实…

还在做互联网创业梦?醒醒!

阅读本文大概需要7分钟。最近国家在互联网领域动作不少&#xff1a;在线教育K12领域被全面整治、阿里被罚款182亿、巨头的垄断和无序扩张遭遇严格限制&#xff0c;大部分互联网上市公司股价一泻千里。身边不少大佬原本身价几千万的期权股票&#xff0c;一瞬间近乎清零&#xff…

把 14 亿中国人民都拉到一个微信群里在技术上能实现吗?

全世界只有3.14 % 的人关注了爆炸吧知识作者丨Max 链接&#xff1a;zhihu.com/question/293021546/answer/487157602把 14 亿中国人民都拉到一个微信群里在技术上能实现吗&#xff1f;先说结论&#xff1a;也许可以实现&#xff0c;但你会什么都看不见。根据 2017 年《微信数据…

使用C#为.NET Interactive开发自定义扩展

在前面的文章中&#xff0c;我们介绍了如何在.NET Interactive notebook绘制图表和执行SQL。那么&#xff0c;能不能为.NET Interactive开发交互功能呢&#xff1f;今天&#xff0c;我们就来演示如何实现。创建项目新建类库项目Demo1Extension&#xff0c;需要引用Nuget包Micro…

zabbix snmp自定义OID nginx监控实例(55)

为什么80%的码农都做不了架构师&#xff1f;>>> 为什么要自定义OID&#xff1f; 前面的文章我们已经讲过zabbix如何使用snmp监控服务器&#xff0c;但是他有一个很明显的局限性&#xff1a;只能监控定义好的OID项目&#xff0c;假如我们想知道nginx进程是否在运行…

(转帖)对抽象编程:接口和抽象类

[你必须知道的.NET] 第二回&#xff1a;对抽象编程&#xff1a;接口和抽象类-王涛 [你必须知道的.NET] 第二回&#xff1a;对抽象编程&#xff1a;接口和抽象类 Author&#xff1a;王涛 Date&#xff1a;2007-4-12 ©2007 Anytao.com 转贴请注明出处&#xff0c;留此信息。…

实验四 图的遍历算法设计与实现

一、实验名称&#xff1a;图的遍历算法设计与实现 二、实验目的&#xff1a; 1.掌握图的深度优先遍历的算法。 2.掌握图的广度优先遍历的算法。 3.实验章节&#xff1a;算法设计与分析 第四章 三、实验内容。实验问题和程序运行结果 第一部分 广度优先遍历算法 完善下列程序&am…