强大的壳-Shell Script

Shell脚本我们经常会使用,平时自己折腾Nas会用到,工作中为了配置CI会用到,自己的电脑上最近为了配置自己的命令行环境也要使用shell来进行配置。不过之前的shell功力都来自每次使用的时候网上搜索,于是最近就找了一本《Linux命令行与shell脚本编程大全》看了看,看完之后更加感受到Shell的强大,特地写个文章来分享一下。

首先呢,shell它也是一种语言,不过因为使用到的shell环境不同语法会有一些差异,在Linux上我们常用的shell是Bash,在Mac上面常用的shell为zsh,大体的语法相似的。编程语言的基本要素,Shell都是支持的,它支持变量,支持if判断,case选择,循环等结构化的编程逻辑控制,也支持基本的算数运算,同时还支持使用函数来复用代码。 简单介绍一下它的语法,首先是变量。系统为我们已经提供了很多的变量,同时在我们的配置文件中定义的那些变量也是可以读取到的。定义变量语法如下:

bash 复制代码
var=value #注意等号两边不能加空格
echo $var #使用的时候前面要加上$符号
echo ${var}

export varb=b #导出成为环境变量

以上方式定义的变量默认是全局的,比如你在一个函数中定义的,外面也能访问,这是时候可以定义局部变量:

bash 复制代码
local local_var=x #只能在函数中使用

除了普通的变量之外,shell中也是支持数组和Map的,当然要bash 4.0以上才能完整支持,使用如下:

bash 复制代码
declare -A info # 声明一个map
declare -a array #声明一个数组

而如果只是有这些东西的话,还不至于说Shell强大。而shell中可以直接调用命令以及Linux中的一些程序这才是它的强大之处。在python等其他语言中我们也是可以调用的,但是是都需要通过语言的系统调用才能调用,而shell中则是可以直接调用那些命令,只要这些程序的可执行文件在PATH环境变量中就可以。

而配合Shell的很多特性,又进一步强大了。第一大神器是重定向,重定向支持重定向输入和重定向输出,以下为一些示例:

bash 复制代码
date > test.txt #重定向输出到test.txt文件中,覆盖文件
ls >> test.txt #重定向,但是追加而不是覆盖文件
wc < test.txt #输入重定向
wc << EOF      #内敛输入重定向
test a
test b
EOF

因为有了输入输出重定向,我们会有很多的玩法,可以方便的命令的输入写入到我们的文件中,而linux系统中,万物皆为文件,因此理论上可以写入或者读取所有东西。比如,有一个Null设备,我们可以通过以下的命令,来不展示任何运行输出。

bash 复制代码
ls >/dev/null 2>&1
ls 1>/dev/null 2>/dev/null

1为标准输出,2为错误输出,未指定的时候默认是把标准输出重定向,这里重定向到null则不会有任何输出,而第一行我们将错误输出又通过&绑定到了标准输出。当然除了这个还有更多的用法。

除了重定向之外的另一大特性则是 管道 。在某些场景重定向已经可以解决了很多功能,但是管道实现会更优雅。管道可以将前一个命令的输出直接传给另一个命令,并且管道的串联没有数量的限制,并且前一个命令产生输出就会传递到第二个命令,不用使用缓冲区或者文件。比如:

bash 复制代码
ls | sort | more

甚至我们还可以将刚刚的输出继续重定向保存到文件

bash 复制代码
ls | sort > files.txt

在很多命令的参数之类的都提供了正则表达式的支持,正则表达式能够让我们更加方便的进行数据匹配,Linux中常用正则为POSIX正则表达式,而它又有两种,基础正则表达式(BRE)和扩展正则表达式(ERE),大部分的Linux/Unix工具都支持BRE引擎规范,仅仅通过BRE就能完成大部分的文本过滤了,但是ERE提供了更强的功能,而有些工具为了速度,也仅仅实现了BRE的部分功能。

BRE支持的语法符号包括,.匹配任意一个字符,[]字符集匹配,[^]字符集否定匹配,^匹配开始位置, $匹配结束位置,()子表达式,*任意次数量匹配(0次或多次),而ERE在BRE的基础上,还支持?最多一次匹配,+匹配至少一次。而它们的更多功能可以参看这篇文章:en.wikibooks.org/wiki/Regula...。

有了正则表达式以及许多的处理工具我们就可以做很多的事情了,比如说查找文件,我们可以使用find,查找某个文件夹下面为指定后缀的文件:

bash 复制代码
find . -type f -name "*.java" #find支持的只是通配符,非正则

而配合管道,又可以对find之后的结果进行进一步的处理,比如配合上grep可以进一步对文件的内容进行过滤。

bash 复制代码
find . -type f -name "*.sh" |xargs grep "bash" #find 不能通过管道直接传递可以使用xargs或者通过如下方式
find . -type f -name "*.sh" -exec grep "bash" {} \;

对于文本的处理,Linux中又有sed和awk两大杀器,而关于他们的使用已经可以被写成书了。sed全名为Stream editor,也就是流编辑器,通过它可以方便的查找文件内容并替换后输出,awk则是一种模式匹配和文字处理语言,通过他们可以方便的处理文本。比如说我们可以使用sed对一份CSV文件中的手机号码进行打码处理:

bash 复制代码
sed -E 's/([0-9]{3})[0-9]{4}([0-9]{4})/\1**\2/g' input.csv

以上关于命令的介绍只是抛砖引玉,关于他们的使用,我们的电脑中已经给我们提供了详细的介绍,只需要在命令行中输入man commandname就可以了,除此之外,很多的命令也也提供了简单的帮助,只需要输入commandname help, command --help之类的就可以看到。

如果仅仅是语言层面的功能的话,shell相比python是没什么优势的,但是它能够和其他的命令无缝的使用,并且被Mac,Linux,Unix内置可直接使用也是它的一大优势。此外我们还可以通过shell脚本来增强我们的Linux终端,比如说可以定义自己的函数,通过.bashrc引用,可以在终端中直接调用方法名执行。

通过Shell,在Linux下面的体验得到很好的提升,工作效率也可以获得很大的提高,本文只是略微提到其皮毛,希望能够引起你对Shell的兴趣,如果想要更加深入的了解,还是需要去阅读手册或者书籍。

以下是推荐的一些资料可供参考:

  1. Bash脚本编程入门 by阮一峰
  2. Bash脚本进阶指南
  3. Grep,Sek和awk的区别
  4. 《Linux命令行与Shell脚本编程大全》(可以在微信读书中看电子书)
  5. awesome-shell (值得看看的各种资料,也可以去看看别人写的shell脚本)
相关推荐
张张123y1 小时前
2026 Agent 框架怎么选?拆 3 层底层逻辑(运行循环 / 记忆 / 工具协议)+ 一张决策表
linux·ubuntu·microsoft·langgraph·mcp·crewai·agent 框架
零域行者1 小时前
Linux入门基础命令
linux·服务器·安全·web安全
打工仔折腾 AI1 小时前
Linux 网络编程:从零掌握 TCP Socket 编程与 C++ 实战落地
linux·网络·人工智能·后端·python·tcp/ip·性能优化
硅基手札1 小时前
SPI技术系列 13 · SPI 调试与排查
linux·运维·stm32·单片机·嵌入式硬件·bug
小兔子1 小时前
Linux 的 write 返回成功,数据到底落在哪了
linux
我命由我123451 小时前
Python 开发 - Python 项目部署(Windows 与 Linux)
java·linux·windows·后端·python·java-ee·python3.11
erzong2311 小时前
Linux操作系统:基于环形队列&信号量实现多生产者多消费者的简易模型
linux·运维·服务器
小羊没烦恼!2 小时前
TypedSql:在 C# 类型系统上实现一个 SQL 查询引擎
java·linux·运维·服务器·开发语言·数据库·mysql
星恒随风2 小时前
Linux线程同步与互斥(二):从日志系统与线程池设计,到线程安全单例、可重入函数和死锁原理
linux·运维·状态模式
mengge.cloud2 小时前
1022小白入门教程(番外筑基)— nerdctl 容器基本功 + K8s 资源编写
linux·网络·云原生·容器·kubernetes·云计算·k8s