如何用jeecg建设网站,wordpress如何设置关键词和描述,网站租用一年服务器费用多少,网站建设公司龙头这节主要是shell部分的内容。
基础知识
概念 这个单词的原意是“外壳”#xff0c;跟 kernel#xff08;内核#xff09;相对应#xff0c;比喻内核外面的一层#xff0c;即用户跟内核交互的对话界面。 具体来说#xff0c;Shell 这个词有多种含义。 首先#xff0c;S… 这节主要是shell部分的内容。
基础知识
概念 这个单词的原意是“外壳”跟 kernel内核相对应比喻内核外面的一层即用户跟内核交互的对话界面。 具体来说Shell 这个词有多种含义。 首先Shell 是一个程序提供一个与用户对话的环境。这个环境只有一个命令提示符让用户从键盘输入命令所以又称为命令行环境commandline简写为 CLI。Shell 接收到用户输入的命令将命令送入操作系统执行并将结果返回给用户。 其次Shell 是一个命令解释器解释用户输入的命令。它支持变量、条件判断、循环操作等语法所以用户可以用 Shell 命令写出各种小程序又称为脚本script。这些脚本都通过 Shell 的解释执行而不通过编译。 最后Shell 是一个工具箱提供了各种小工具供用户方便地使用操作系统的功能。 网上有很多 shell 的概念介绍其实都很官方化如果你对 linux 命令很熟悉那么编写 shell 就不是一个难事shell 本质上是 linux 命令一条一条命令组合在一起实现某一个目的就变成了 shell 脚本。它从一定程度上减轻了我们的工作量提高了工作效率。
历史 Shell 伴随着 Unix 系统的诞生而诞生。 1969年Ken Thompson 和 Dennis Ritchie 开发了第一版的 Unix。 1971年Ken Thompson 编写了最初的 Shell称为 Thompson shell程序名是 sh方便用户使用 Unix。 1973年至1975年间John R. Mashey 扩展了最初的 Thompson shell添加了编程功能使得 Shell 成为一种编程语言。这个版本的 Shell 称为 Mashey shell。 1976年Stephen Bourne 结合 Mashey shell 的功能重写一个新的 Shell称为 Bourne shell。 1978年加州大学伯克利分校的 Bill Joy 开发了 C shell为 Shell 提供 C 语言的语法程序名是 csh 。它是第一个真正替代 sh 的 UNIX shell被合并到 Berkeley UNIX 的 2BSD 版本中。 1979年UNIX 第七版发布内置了 Bourne Shell导致它成为 Unix 的默认 Shell。注意Thompson shell、Mashey shell 和 Bourne shell 都是贝尔实验室的产品程序名都是 sh 。对于用户来说它们是同一个东西只是底层代码不同而已。 1983年David Korn 开发了Korn shell程序名是 ksh 。 1985年Richard Stallman 成立了自由软件基金会FSF由于 Shell 的版权属于贝尔公司所以他决定写一个自由版权的、使用 GNU 许可证的 Shell 程序避免 Unix 的版权争议。 1988年自由软件基金会的第一个付薪程序员 Brian Fox 写了一个 Shell功能基本上是 Bourne shell 的克隆叫做 Bourne-Again SHell简称 Bash程序名为 bash任何人都可以免费使用。后来它逐渐成为 Linux 系统的标准 Shell。 1989年Bash 发布1.0版。 1996年Bash 发布2.0版。 2004年Bash 发布3.0版。 2009年Bash 发布4.0版。 2019年Bash 发布5.0版。 种类 Shell 有很多种只要能给用户提供命令行环境的程序都可以看作是 Shell。 历史上主要的 Shell 主要有 Bourne Shellsh、Bourne Again shellbash、C Shellcsh、TENEX C Shelltcsh、Korn shellksh、Z Shellzsh、Friendly Interactive Shellfish等。 因为后续都是用bash举例所以这里在介绍 bash 外只简单延伸一下其他的shell。
Bourne Again Shell Bash 是目前最常用的 Shell也就是Bourne Again Shell。Bash由于易用和免费在日常工作中被广泛使用也是大多数Linux操作系统默认的Shell环境。除非特别指明下文的 Shell 和 Bash 当作同义词使用可以互换。 Bash 于 1989 年首次发布它是大多数 Linux 发行版的默认 Shell 环境。其他发行版如 Kali Linux使用 Z Shell 作为默认 shell。 Bash 也是 Linus TorvaldsLinux 的创建者移植到 Linux 的首批程序之一。
Bash 的关键点 1、因为 Bash 是大多数系统上的默认 shell 环境大多数用户使用它。 2、Bash 没有内联通配符表达式。通配符表达式是当你想要在 Shell 中搜索模式pattern的时候使用类似于正则表达式Regex。三个主要的通配符是 * 、? 和 [] 。 3、不能自动更改目录名称。 4、# 在脚本中被视为注释。 5、Bash 有 shoptshell option 缩写设置。 6、提示符prompt有反斜杠转义。 7、用户配置设置在 .bashrc 中。
Z Shell Z Shell 又称 Zsh 是一个与 Bash 非常相似的 UNIX shell。你还可以使用 Zsh 编写脚本并将 shell 用作命令解释器。 Zsh 是 Bourne shell 的扩展因此在此之上很多改进。Zsh 于 1990 年由 Paul Falstad 发布它具有 Bash、Korn Shell 和 C Shell 共有的一些功能。 macOS 默认使用 Zsh Shell。
Zsh 的关键点 1、在终端使用时Zsh 带有自动补全功能。因此当你按下 Tab 键以自动补全你想运行的任何命令时它不仅为你自动补全而且弹出下拉菜单包含所有其他可能的文件和目录。 2、支持内联通配符表达式。 3、比 Bash 可配置度更高。 4、支持插件和主题。 同时还有围绕 Z Shell 构建的框架。最受欢迎的框架之一是 Oh My Zsh它是一个社区驱动的开源框架用于管理 Zsh 配置。 Zsh 和 Oh My Zsh 很相似但并不完全相同。另外Oh My Zsh 是一种管理 Zsh 配置的方式它不是 Shell 本身。
Fish Shell Fish 是一个强调交互性和可用性的 UNIX shell 环境。与 Zsh 不同Fish 旨在为用户提供交互性而不是信任用户实现自己的配置。 它由 Axel Liljencrantz 于 2005 年创建。由于不符合 POSIX shell 标准Fish 被认为是奇异的 shell。
Fish 的关键点 1、Fish 根据你的命令历史记录和所在目录提供“键入时搜索”自动建议。与 Bash 的历史搜索类似Fish Shell 的搜索历史始终处于打开状态。这样用户终端工作时能够获得交互式反馈。 2、Fish 还倾向将功能作为命令而不是语法。这使得功能的选项和帮助文本可见。 3、由于默认情况下 Fish 已经预置了很多配置因此它被认为比 Zsh 等其他 sh 选项更适合初学者。 4、Fish 的脚本语言不同于 Zsh 和 Bash。 Zsh 使用更多简化指令alias而 Fish 避免在脚本语言中使用简化指令。 如果你只是使用基本命令如 cd 、cp 、vim 、ssh 等编写脚本你将不会注意到 Fish 和 Bash 的脚本语言的工作方式有何不同。 Bash、Z Shell 和 Fish Shell 各有优点也有一些相似之处。如果你想要更可配置的 shell你可以使用 Zsh甚至安装 Oh My Zsh。如果你想要更多交互的终端体验同时不需要大量配置你可以使用 Fish Shell。如果你想要经典的感觉你可以保留 Bash。 下面的命令可以查看当前运行的 Shell效果图如下。
echo $SHELL 下面的命令可以查看当前的 Linux 系统安装的所有 Shell效果图如下。
cat /etc/shells Linux允许每个用户使用不同的Shell但用户的默认Shell 一般都是Bash或者与Bash兼容。
作用 Shell 是操作系统中的一个重要组成部分它充当用户与操作系统之间的接口下面是 Shell 在操作系统中所扮演的几个主要角色和作用。
命令解释器Shell 是一个命令解释器用户通过它输入命令Shell 将这些命令解析并传递给操作系统执行。它能够理解用户输入的命令并将其转换为操作系统可以执行的操作用户界面Shell 提供了一个用户界面通常是命令行界面用户可以通过输入命令来与操作系统进行交互。尽管现代操作系统也有图形用户界面GUI但命令行界面仍然在系统管理、开发和自动化任务中被广泛使用 脚本编程Shell 支持脚本编程用户可以编写 Shell 脚本来自动执行一系列命令。这使得用户能够创建复杂的任务和自动化流程从而提高工作效率例如系统管理员可以编写脚本来定期备份文件或监控系统状态进程控制Shell 允许用户启动、停止和管理进程。用户可以在 Shell 中运行程序、将其放入后台或前台、以及终止进程。Shell 还提供了作业控制功能允许用户在多个进程之间进行切换环境管理Shell 提供了环境变量的管理功能用户可以设置和修改环境变量以影响系统和应用程序的行为。环境变量可以用于存储配置信息如路径、用户信息等文件操作Shell 为用户提供了丰富的文件操作命令用户可以轻松地创建、删除、移动、复制和编辑文件和目录。Shell 还支持重定向和管道允许用户灵活地处理输入和输出系统管理工具Shell 提供了许多系统管理工具管理员可以使用 Shell 来监控系统状态、管理用户、配置网络以及执行其他系统管理任务命令组合与脚本控制Shell 支持命令组合、条件执行和循环控制使得用户能够编写复杂的逻辑。用户可以使用条件语句如 if ,case和循环结构如 for , while 来控制程序的执行流。 基础操作 基本的命令行操作需要掌握比如 ls、cd、cp、mv、mkdir、grep等这里因为在前面的笔记中已经讲过所以这里不再展开介绍。 基础语法 这里先介绍一个shell编程注意事项。 1、Shell 脚本名称命名一般为英文、大写、小写后缀以 . sh 结尾。 2、不能使用特殊符号、空格。 3、名称最好可以一下看出功能。 4、首行需要 #!/bin/bash 开头。 5、shell 脚本 变量 不能以 数字、特殊符号开头可以使用下划线—, 但不能 用破折号 - 。
变量 在 Shell 编程中变量是用于存储数据值的名称。 Shell 是一种动态类型语言不使用显式的数据声明和弱类型语言变量的类型操作根据需求而不同。Shell中的变量是不分类型的都是字符串类型但是依赖于具体的上下文Shell编程也允许比较操作和整数操作。 Shell变量名在定义时首个字符必须为字母a-zA-Z不能以数字开头中间不能有空格可以使用下划线_不能使用-也不能使用标点符号等。 定义变量时变量名不加美元符号$PHP语言中变量需要。
分类 shell 里的变量可以分为环境变量和自定义变量。 环境变量 通常情况下每个进程都有自己的“环境”这个环境是由一组变量组成的这些变量中存有进程可能需要引用的信息。在这种情况下Shell 与一般的进程没有什么区别。 环境变量是系统提供的共享变量是 linux 系统加载 shell 的配置文件中定义的变量共享给所有的 shell 程序使用。环境变量按照其作用范围不同大致可以分为系统级环境变量和用户级环境变量。 这里的系统级环境变量指的是 shell 环境加载全局配置文件中的变量共享给所有用户所有shell程序使用实现全局共享而用户级环境变量是指 shell 环境加载个人配置文件中的变量共享给当前用户的 shell 程序使用即登录用户使用。 全局配置文件一般在 /etc/profile、/etc/profile.d/*.sh、/etc/bashrc。 个人配置文件一般在当前用户/.bash_profile、当前用户/.bashrc。 查看系统环境变量的方法 - env 或者 set。
# 查看当前Shell系统环境变量
env
# 查看Shell变量(系统环境变量自定义变量函数)
set 效果图如下这里用我自己虚拟的效果来举例说明set 的效果太长了这里就不做展示。 常见的环境变量如下。
PATH设置命令的搜索路径以冒号为分割LANG字符集以及语言编码PS1Shell 提示符PS2 输入多行命令时次要的 Shell 提示符PWD当前工作目录HOME当前用户主目录SHELL当前shell解析器类型HISTFILE显示当前用户执行命令的历史列表文件OLDPWD显示之前的路径HOSTNAME显示当前主机名HOSTTYPE显示主机的架构TERM终端类型名即终端仿真器所用的协议 很多环境变量很少发生变化而且是只读的可以视为常量。由于它们的变量名全部都是大写所以传统上如果用户要自己定义一个常量也会使用全部大写的变量名。 注意Bash 变量名区分大小写比如 HOME 和 home 是两个不同的变量。 查看单个环境变量的值可以使用 printenv 命令或 echo 命令。
printenv 变量名 # 这里不用加$前缀
echo $变量名 效果图如下。 自定义变量 自定义变量是用户在当前 Shell 里面自己定义的变量必须先定义后使用而且仅在当前 Shell 可用。一旦退出当前 Shell该变量就不存在了。 在 Shell 编程中变量可以根据其作用域和使用方式进行分类自定义变量按照不同标准的分类各不相同比如数组变量、特殊变量、只读变量、用户变量包括全局变量和局部变量、位置变量等。 这里简单介绍其中几个。
用户变量 用户在 Shell 编程过程中定义的变量分为全局变量和局部变量。默认情况下用户定义的Shell 变量为全局变量如果要指定局部变量则需使用 local 限定词。
位置变量 位置变量也称系统变量或位置参数是 Shell 脚本运行时传递给脚本的参数同时也表示Shell 脚本内部的函数参数。 它们的名称是以数字命名出于历史原因直接引用的位置参数只能从0~9即$0~$9超过这个范围的必须用括号括起来如 ${10} 。
特殊变量 特殊变量是系统预定义的变量用于提供关于当前 shell 或进程的信息。 $#变量个数、$?上条命令的结束值、$*所有参数、$与S*同义在双引号中时每个参数作为独立的参数等。 注意当 S* 和 $ 在 中时他们的意义不同$* 值是一个字串$ 值是N个字串。 下面是部分效果图。 上面的 $0 永远都会是脚本名或者包含脚本名。 只读变量 只读变量在定义后不能被修改。使用 readonly 命令设置。
readonly my_varThis is readonly
使用
变量定义规则 1、变量名称可以有字母,数字和下划线组成, 但是不能以数字开头。 2、等号两侧不能有空格。 3、在 bash 环境中, 变量的默认类型都是字符串类型, 无法直接进行数值运算。 4、变量的值如果有空格, 必须使用双引号括起来。 5、不能使用 Shell 的关键字作为变量名称。 注意变量名和等号之间不能有空格这可能和我们之前熟悉的所有编程语言都不一样。
变量名的命名规则 1、只包含字母、数字和下划线 变量名可以包含字母大小写敏感、数字和下划线 _不能包含其他特殊字符。 2、不能以数字开头 变量名不能以数字开头但可以包含数字。 3、避免使用 Shell 关键字 不要使用 Shell 的关键字例如 if、then、else、fi、for、while 等作为变量名以免引起混淆。 4、使用大写字母表示常量 习惯上常量的变量名通常使用大写字母例如 PI3.14。 5、避免使用特殊符号 尽量避免在变量名中使用特殊符号因为它们可能与 Shell 的语法产生冲突。 6、避免使用空格 变量名中不应该包含空格因为空格通常用于分隔命令和参数。 在Bash 没有数据类型的概念所有的变量值都是字符串。 通过在变量名前添加 $ 字符来引用变量的值此过程也叫变量替换。 在定义变量时若 string 包含空格制表符和换行符则 string 必须用 string 和 string 的形式即用单引号或双引号将其括注双引号内允许变量替换而单引号内不可以。
读取变量 读取一个定义过的变量只要在变量名前面加美元符号即可如果变量不存在Bash 不会报错而会输出空字符。 下面是部分效果图。 这里的 { } 加不加都可以加主要是为了帮助解释器识别变量的边界下面这种就需要。 删除变量 使用 unset 命令可以删除变量。
unset 变量名 变量被删除后不能再次使用unset 命令不能删除只读变量。 因为不存在的 Bash 变量一律等于空字符串所以即使 unset 命令删除了变量还是可以读取这个变量值为空字符串。 所以删除一个变量也可以将这个变量设成空字符串。 输出变量export 命令 用户创建的变量仅可用于当前 Shell子 Shell 默认读取不到父 Shell 定义的变量。为了把变量传递给子 Shell需要使用 export 命令。 这样输出的变量对于子 Shell 来说就是环境变量。 export 命令用来向子 Shell 新增修改或删除环境变量供后续执行的程序使用。
# 这里是安装 nginx 后增加环境变量
export PATH$PATH:/usr/local/nginx 子 Shell 如果修改继承的变量不会影响父 Shell。
字符串 字符串是 shell 编程中最常用最有用的数据类型字符串可以用单引号或者双引号也可以不用引号。都必须是英文格式的符号
表示格式
单引号
astart 限制 1、单引号里的任何字符都会原样输出单引号字符串中的变量是无效的。 2、单引号字符串中不能出现单独一个的单引号对单引号使用转义符后也不行但可成对出现作为字符串拼接使用。
双引号
astart 优点 1、双引号里可以有变量。 2、双引号里可以出现转义字符。
拼接字符串
# 双引号拼接
aalice
allhello,$a
echo $all
all_1hell0,${a}
# 单引号拼接
aalice
all_2hello,$a
echo $all_2
all_3hello,${a}
echo $all_3
# 从下面的效果图可以得知单引号无法拼接带有变量的字符串 这里看到使用单引号不会成功只能使用双引号。
获取字符串长度
a字符串
echo ${#a} / echo ${#a[0]}
# 变量为字符串时${#string} 等价于 ${#string[0]}
# 因为 ${#string[0]} 返回的是数组或字符串的第一个字符的长度 具体效果图如下。 提取子字符串
a字符串
echo ${a:数字1:数字2}
# 这里的数字1是指从索引为数字1的字符开始提取
# 这里的数字2是指到索引为数字2的字符结束提取
# 数字为负数则表示从末尾开始倒着找 效果图如下。 查找子字符串
a字符串
echo $(expr index $a 子字符串) 效果图如下。 还有更多使用方法如下。
搜索和替换 Bash 提供字符串搜索和替换的多种方法格式如下。 格式 说明 示例 ${变量名/旧字符串/新字符串} 将旧字符串替换成新字符串仅替换第一个 ${path/aaa/AAA}将aaa替换成AAA仅替换第一个 ${变量名//旧字符串/新字符串} 将旧字符串替换成新字符串替换所有 ${path//aaa/AAA}将aaa替换成AAA所有的都替换
字符串头部的模式匹配 以下两种语法可以检查字符串开头是否匹配给定的模式。如果匹配成功就删除匹配的部分返回剩下的部分原始变量不会发生变化。
# 如果 pattern 匹配变量的开头就删除最短匹配非贪婪匹配的部分返回剩余部分
${变量名#pattern}# 如果 pattern 匹配变量的开头就删除最长匹配贪婪匹配的部分返回剩余部分
${变量名##pattern}
# 模式 pattern 可以用 *、?、[] 等通配符。 上面两种语法会删除变量字符串开头的匹配部分将其替换为空返回剩下的部分。 区别是一个是最短匹配又称非贪婪匹配另一个是最长匹配又称贪婪匹配。 从上图中可以看出一个 # 是最短匹配适合和 ? 一起使用两个 ## 是最长匹配如果开头符合就删除所有适合和 * 一起使用。 匹配不成功就会返回原始字符串。 要将头部匹配的部分替换成其他内容的话可以参考下面的写法。
aone
echo ${a/#o/s}
# 输出 sne部分效果图如下。 上面例子中被替换的部分必须出现在字符串头部。
字符串尾部的模式匹配 下面两种语法可以检查字符串结尾是否匹配给定的模式。 如果匹配成功就删除匹配的部分返回剩下的部分。原始变量不会发生变化。
# 如果 pattern 匹配变量的结尾
# 删除最短匹配非贪婪匹配的部分返回剩余部分
${变量名%pattern}# 如果 pattern 匹配变量的结尾
# 删除最长匹配贪婪匹配的部分返回剩余部分
${变量名%%pattern} 上面两种语法会删除变量字符串结尾的匹配部分将其替换为空返回剩下的部分。区别是一个是最短匹配又称非贪婪匹配另一个是最长匹配又称贪婪匹配。 如果匹配不成功则返回原始字符串。 要替换尾部匹配的部分用法和上面的头部替换差不多。
btwo
echo ${b/%o/n}
# 输出 twn 上面例子中被替换的部分必须出现在字符串尾部。
任意位置的模式匹配 下面种语法可以检查字符串内部是否匹配给定的模式。 如果匹配成功就删除匹配的部分换成其他的字符串返回。原始变量不会发生变化。
# 如果 pattern 匹配变量的一部分
# 最长匹配贪婪匹配的那部分被新字符串替换但仅替换第一个匹配
${变量名/pattern/替换字符串}# 如果 pattern 匹配变量的一部分
# 最长匹配贪婪匹配的那部分被新字符串替换所有匹配都替换
${变量名//pattern/替换字符串} 上面两种语法都是最长匹配贪婪匹配下的替换区别是前一个语法仅仅替换第一个匹配后一个语法替换所有匹配。改变大小写 下面的语法可以改变变量的大小写效果图如下。
echo ${变量名^^} # 转大写
echo ${变量名,,} # 转小写 数组 数组中可以存放多个值。 Bash Shell 只支持一维数组不支持多维数组初始化时不需要定义数组大小。 这里的数组和大部分编程语言类似里面元素的下标都从 0 开始。 Shell 数组用括号来表示元素用空格符号分割开。
all(a b c d e ...) # 形式类似注意空格
all[索引数]自定义 # 这是单个定义的方法
echo ${all[索引数]} # 这是读取方法 部分效果图如下。 运算符
算术运算符
运算符说明运算符说明加法-减法*乘法/除法%取余赋值相等!不相等 实现算术运算可以用下面的两种办法部分效果图如下。
# 第一种
echo $((...))
# 第二种
a expr ...
echo $a
# 这里的 ... 都是具体的运算表达式比如 32、8*3 等a 也是自定义变量名。 关系运算符
运算符说明运算符说明-eq检测两个数是否相等-ne检测两个数是否不相等-gt检测左边的数是否大于右边的-lt检测左边的数是否小于右边的-ge检测左边的数是否大于等于右边的-le检测左边的数是否小于等于右边的
· 满足说明的就会返回 true部分效果图如下。 布尔运算符
运算符说明非运算表达式为 true 则返回 false否则返回 true-o或运算有一个表达式为 true 则返回 true-a与运算两个表达式都为 true 才返回 true 部分效果图如下。 温馨提示 [] 里一定要记得空格。
逻辑运算符
运算符说明运算符说明逻辑的 and||逻辑的 or 部分效果图如下。 注意这里需要用 [[]] 不能用 [] 。
字符串运算符
运算符说明检测两个字符串是否相等相等返回 true!检测两个字符串是否不相等不相等返回 true-z检测字符串长度是否为0为0返回 true-n检测字符串长度是否不为 0不为 0 返回 true$检测字符串是否不为空不为空返回 true 部分效果图如下。 文件测试运算符
操作费说明操作费说明-b file检测文件是否是块设备文件如果是则返回 true-c file检测文件是否是字符设备文件如果是则返回 true-d file检测文件是否是目录如果是则返回 true -f file 检测文件是否是普通文件既不是目录也不是设备文件如果是则返回 true-g file检测文件是否设置了 SGID 位如果是则返回 true-k file检测文件是否设置了粘着位(Sticky Bit)如果是则返回 true -r file 检测文件是否可读如果是则返回 true-w file检测文件是否可写如果是则返回 true-s file检测文件是否为空文件大小是否大于0不为空返回 true-e file检测文件包括目录是否存在如果是则返回 true-p file检测文件是否是有名管道如果是则返回 true-u file检测文件是否设置了 SUID 位如果是则返回 true 部分效果图如下。 条件判断
if 结构 if 是最常用的条件判断结构通常以 if 开头fi 结尾只有符合给定条件时才会执行指定的命令。
# 单分支语句
if 条件表达式 ; then语句
fi
# 也可以写成单行
if 条件表达式 ; then 语句 ; fi
# 双分支语句
if 条件表达式 ; then语句
else语句
fi
# 多分支语句
if 条件表达式 ; then语句
elif 条件表达式 ; then语句
elif 条件表达式 ; then语句
fi 这里 if 关键字后面是主要的判断条件elif 用来添加在主条件不成立时的其他判断条件else则是所有条件都不成立时要执行的部分。 注意在命令中用到定义的变量时必须在前面加上 $ 符号还有涉及到变量的条件表达式必须是 test 命令形式下面会介绍还有比较运算符因为在前面已经介绍过这里就不讲了。 下面是一个例子的效果图。 test 命令 if 结构的判断条件一般使用 test 命令有三种形式。
# 写法一
test 表达式
# 写法二
[ 表达式 ]
# 写法三
[[ 表达式 ]]
# 后面两种都要注意有空格 上面三种形式是等价的但是第三种形式还支持正则判断前两种不支持。 单独 test 命令作用检查某个条件是否成立,返回值为0真或者其他值假可通过 echo $? 查看返回值和 if 、for 结合也常用于条件和循环语句。 一般用于判断文件是否存在、比较字符串和数值。 判断文件或者文件夹的参数如下。
参数说明参数说明参数说明-e当路径存在时返回真-f路径存在且为文件时返回真-d路径存在且为文件夹时返回真 部分效果图如下。 比较字符串的参数如下。
参数说明参数说明-z当字符串为空时返回真-n当字符串为非空时返回真/两个字符串相等时返回真!两个字符串不等时返回真 部分效果图如下。 比较数值的参数如下就是前面的算术运算符后面的参数应该都能在前面找到就不再多介绍一遍了部分效果图如下。 判断表达式 if 关键字后面跟的是一个命令。这个命令可以是 test 命令也可以是其他命令。命令的返回值为 0 表示判断成立否则表示不成立。因为这些命令主要是为了得到返回值所以可以视为表达式。 下面列举几个常用的表达式判断运算符都在前面可以找到。
文件判断 字符串判断 整数判断 正则判断 具体的正则表达式会在后面介绍这里先简单举个例子。
^[a-zA-Z]$
# 下面是解析
# ^
# 这个符号表示字符串的开始。它确保匹配的字符串从开头开始
# [a-zA-Z]
# 方括号 [] 表示一个字符类表示可以匹配方括号内的任意一个字符
# a-z 表示所有小写字母从 a 到 z
# A-Z 表示所有大写字母从 A 到 Z
# 所以[a-zA-Z] 可以匹配任意单个字母不论是大写还是小写
#
# 这个符号表示前面的字符类即 [a-zA-Z]可以出现一次或多次。也就是说至少需要一个字母但可以有多个字母
# $
# 这个符号表示字符串的结束。它确保匹配的字符串在结尾处结束
# 结合这些部分正则表达式 ^[a-zA-Z]$ 的整体含义如下
# 匹配一个由字母组成的字符串该字符串可以包含一个或多个字母但不能包含其他字符如数字、符号或空格并且该字符串必须从开始到结束都是字母 效果图如下。 算术判断 这里主要就是用 (( )) 来实现。 逻辑判断 主要用到的就是 AND和 ||OR还有 !NOT。 case 结构 case 结构用于多值判断可以为每个值指定对应的命令跟包含多个 elif 的 if 结构等价但是语义更好。
case 条件表达式 in表达式的值/一种模式 ) 语句;;表达式的值/一种模式 ) 语句;;...
esac 具体效果图如下。 循环结构 Bash 提供三种循环语法 for、while、until 。
while 循环 while 循环有一个判断条件只要符合条件就不断循环执行指定的语句。
while 条件表达式
do语句
done
# do 在第一行的话就需要在前面加一个分号注意空格 条件表达式可以使用 test 命令跟 if 结构的判断条件写法一致。 until 循环 until 循环与 while 循环恰好相反只要不符合判断条件判断条件失败就不断循环执行指定的语句。
until 条件表达式
do语句
done
# do 在第一行的话就需要在前面加一个分号注意空格 until 循环都可以转为 while 循环只要把条件设为否定即可但一般 until 用得比较少。
for 循环 for 循环除了和上面相似的使用架构外还有一个经常使用的 for ... in ... 循环架构。
for ((表达式)) ; do语句
donefor 变量名 in 列表比如数组; do语句
done# do 在第二行就可以不要分号
break 和 continue Bash 提供了两个内部命令 break 和 continue 用来在循环内部跳出循环。 break 命令立即终止循环程序继续执行循环块之后的语句即不再执行剩下的循环。 上面只要变量N等于10就跳出循环并输出此时的变量值。 continue 命令立即终止本轮循环开始执行下一轮循环。 这里主要是为了排除和跳过某些特定的值。
select 结构 select 结构主要用来生成简单的菜单它的语法与 for ... in ... 大致相同。 在 Bash 脚本中select 语句会自动为每个选项分配一个数字索引并将其显示在菜单中。这使得用户可以通过输入对应的数字来选择相应的选项。 这里的 fruit 是用于存储用户选择的变量选项是数组中的所有元素。 函数 函数function是可以重复使用的代码片段有利于代码的复用。它与别名alias的区别是别名只适合封装简单的单个命令函数则可以封装复杂的多行命令。 函数总是在当前 Shell 执行这是跟脚本的一个重大区别Bash 会新建一个子 Shell 执行脚本。如果函数与脚本同名函数会优先执行。但是函数的优先级不如别名即如果函数与别名同名那么别名优先执行。
# 第一种定义语法
自定义名() {# 代码
}
# 第二种定义语法
function 自定义名() {# 代码
} 上面是效果图。
参数变量 函数体内可以使用参数变量获取函数参数而函数的参数变量与脚本参数变量是一致的。
$1~$9函数的第一个到第九个参数$0函数所在脚本名$#函数的参数总和$函数的全部参数彼此间有空格$*函数的全部参数参数之间使用变量 $IFS 值的第一个字符分隔默认为空格但是可以自定义 如果函数的参数多于9个那么第10个参数可以用 ${10} 的形式引用以此类推。 return 命令 return 命令用于从函数返回一个值函数执行到这条命令就不再往下执行直接返回了。 全局变量和局部变量 Bash 函数体内直接声明的变量属于全局变量整个脚本都可以读取。 函数里面可以用 local 命令声明局部变量。 这里因为 b 是局部变量所以在函数结构体外调用时就无法找到。 输入输出
标准输入输出 在 Linux 系统中标准输入stdin、标准输出stdout和标准错误stderr是处理输入和输出的三个基本概念。它们在 Shell 脚本编程中非常重要理解这些概念可以帮助我们更有效地编写和调试脚本。
标准输入stdin 标准输入是程序接收输入数据的默认源通常是键盘。 标准输入的文件描述符是 0可以使用重定向符 将文件内容作为标准输入传递给程序。
# 从文件读取输入
cat input.txt在这个示例中cat 命令从 input.txt 文件中读取内容 标准输出stdout 标准输出是程序输出数据的默认目标通常是终端屏幕。 标准输出的文件描述符是 1可以使用重定向符 将标准输出重定向到文件使用 追加到文件。
# 将输出写入文件
echo Hello, World! output.txt在这个示例中echo 命令的输出被重定向到 output.txt 文件中而不是显示在终端上 标准错误stderr 标准错误是程序输出错误信息的默认目标通常也是终端。 标准错误的文件描述符是 2可以使用重定向符 2 将标准错误重定向到文件使用 2 追加到文件。
# 将错误输出写入错误.log
ls nonexistentfile 2 error.log在这个示例中ls 命令尝试列出一个不存在的文件错误信息被重定向到 error.log 文件中 结合使用 在 Shell 脚本中可以同时处理标准输入、输出和错误。
#!/bin/bash# 读取用户输入
echo 请输入一个文件名
read file# 检查文件是否存在
if [ -e $file ]; thenecho 文件 $file 存在 # 标准输出
elseecho 错误文件 $file 不存在 2 # 标准错误
fi
# 增加执行权限
chmod x 脚本名# 将输出和错误都重定向到文件
./脚本名 output.log 21 效果图如下注意如果将结果重定向到文件中命令行的提示就会消失只能直接输入文件名进行判断。 当然还有另一种办法可以解决这个问题。
#!/bin/bash# 读取用户输入
echo 请输入一个文件名
read file# 检查文件是否存在
if [ -e $file ]; thenecho 文件 $file 存在 | tee -a output.log
elseecho 错误文件 $file 不存在。 2 | tee -a output.log
fi tee 命令是一个非常有用的工具它可以将标准输入的数据同时输出到标准输出和一个或多个文件中。
总结 1、stdin标准输入用于接收输入默认来源是键盘。 2、stdout标准输出用于输出结果默认目标是终端。 3、stderr标准错误用于输出错误信息默认目标也是终端。 4、通过重定向可以将这些输入输出流转发到文件或其他程序。 重定向 重定向指的是将命令行输出写入指定位置。 下面是一些常用的规范。 cmd1 | cmd2 管道将 cmd1 的标准输出作为 cmd2 的标准输入 file将标准输出重定向到文件 file从文件获取标准输入 file 将标准输出重定向到文件如果文件已存在则追加到文件末尾 | file强制将标准输出重定向到文件即使设置了 noclobbern | file强制从文件描述符 n 将输出重定向到文件即使设置了 noclobber file将文件用作标准输入和标准输出n file将文件用作文件描述符 n 的输入和输出 label这里文档参见文本n file将文件描述符 n 的输出重定向到文件n file从文件获取文件描述符 n 的输入n file将文件描述符 n 的输出重定向到文件如果文件已存在则追加到文件末尾n将标准输出复制到文件描述符 nn将标准输入从文件描述符 n 复制nm将文件描述符 n 复制为输出文件描述符nm将文件描述符 n 复制为输入文件描述符file将标准输出和标准错误都重定向到文件-关闭标准输入-关闭标准输出n-关闭文件描述符 n 的输出n-关闭文件描述符 n 的输入 nword如果未指定 n则使用标准输出文件描述符 1如果 word 中的数字未指定一个打开用于输出的文件描述符则会发生重定向错误作为特例如果省略 n并且 word 不展开为一个或多个数字则标准输出和标准错误将按照上面描述的方式重定向nword如果 word 展开为一个或多个数字则文件描述符 n 将成为该文件描述符的副本如果 word 中的数字未指定一个打开用于输入的文件描述符则会发生重定向错误如果 word 的值为 -则关闭文件描述符 n如果未指定 n则使用标准输入文件描述符 0ndigit-将文件描述符 digit 移动到文件描述符 n如果未指定 n则移动到标准输出文件描述符 1ndigit-将文件描述符 digit 移动到文件描述符 n如果未指定 n则移动到标准输入文件描述符 0在复制到 n 后digit 被关闭 这四个可能一下看不明白所以我在这里用几个例子介绍一下。
### 示例 1: nword# 基本用法exec 31 # 将文件描述符 3 重定向到标准输出echo Hello, World! 3 # 将内容输出到文件描述符 3实际上是标准输出# 在这个例子中exec 31 将文件描述符 3 指向标准输出文件描述符 1。接下来的 echo 命令将字符串 Hello, World! 输出到文件描述符 3这意味着它会显示在终端上# 重定向错误示例exec 4- # 关闭文件描述符 4echo Test 4 # 试图将输出重定向到已关闭的文件描述符发生错误### 示例 2: nword# 基本用法
# 假设有一个文件 input.txt内容为HelloWorld
# 下面是脚本内容exec 5 input.txt # 将文件描述符 5 指向 input.txtread line 5 # 从文件描述符 5 读取一行echo Read from file: $line # 输出读取的内容# 在这个例子中exec 5 input.txt 将文件描述符 5 指向 input.txt 文件。接下来的 read 命令从文件描述符 5 中读取一行最后输出读取的内容# 关闭文件描述符示例exec 6- # 关闭文件描述符 6read line 6 # 试图从已关闭的文件描述符读取发生错误### 示例 3: ndigit-# 基本用法exec 71 # 将文件描述符 7 重定向到标准输出echo Standard Output 7 # 这将输出 Standard Output 到标准输出exec 7- # 关闭文件描述符 7# 在这个例子中exec 71 将文件描述符 7 指向标准输出。然后echo 命令将字符串输出到文件描述符 7实际上是标准输出。最后exec 7- 关闭文件描述符 7### 示例 4: ndigit-# 基本用法exec 8 /dev/tty # 将文件描述符 8 指向终端echo Enter something: 8 # 提示用户输入read input 8 # 从文件描述符 8 读取用户输入echo You entered: $input # 输出用户输入exec 8- # 关闭文件描述符 8# 在这个例子中exec 8 /dev/tty 将文件描述符 8 指向终端设备。然后echo 输出提示信息接下来使用 read 从文件描述符 8 读取用户输入最后输出用户输入的内容将标准输出重定向到指定文件 如果重定向后的指定文件已经存在就会被覆盖不会有任何提示。 如果命令没有任何输出那么重定向之后得到的是一个长度为0的文件。 因此 具有创建新文件或改写现存文件、将其改为长度0的作用。 将标准输出重定向追加到指定文件
2 用来将标准错误重定向到指定文件
# 可以用 标准输出和标准错误可以重定向到同一个文件
$ ls -l /bin/usr ls-output.txt 21
# 或者
$ ls -l /bin/usr ls-output.txt# 追加到同一个文件
$ ls -l /bin/usr ls-output.txt# 如果不希望输出错误信息可以将它重定向到一个特殊文件/dev/null
$ ls -l /bin/usr 2 /dev/null| 用于将一个命令的标准输出重定向到另一个命令的标准输入 高级语法
脚本结构
脚本头Shebang 脚本的第一行通常是一个称为“shebang”的行它指明了脚本的解释器。 在 Bash 脚本中shebang 行通常是 #!/bin/bash这告诉系统使用 /bin/bash 解释器来执行该脚本。
注释 在脚本中注释用于提供关于代码的说明和文档注释不会被执行主要用于提高代码的可读性。 Bash 中的注释以 # 开头直到行尾。
# 这是一个示例脚本
echo Hello, World! # 输出 Hello, World!
变量 在脚本中可以定义和使用变量。 变量不需要提前声明直接赋值即可。
nameAlice
echo Hello, $name!
控制结构 脚本通常包含控制结构例如条件语句和循环上面有详细介绍这里就不再展开。
函数 可以在脚本中定义函数来组织代码并提高可重用性。
执行权限 在 Linux 中脚本需要具有执行权限才能运行。可以使用 chmod 命令来设置权限。
chmod x 脚本名 # 给 script.sh 添加执行权限# 设置好权限后可以通过以下方式执行脚本
./脚本名 # 在当前目录下执行脚本
输入和输出 脚本可以处理输入和输出包括从用户获取输入和将输出重定向到文件。
# 用户输入read -p Enter your name: nameecho Hello, $name!# 重定向输出echo This will be saved to a file output.txt # 将输出重定向到文件
错误处理 可以通过检查命令的退出状态$?来进行错误处理。
mkdir new_directory
if [ $? -ne 0 ]; thenecho Failed to create directory!
fi
# 原理是如果命令执行成功echo $? 将会返回0的结果非0则有错误。
退出状态
脚本可以使用 exit 命令返回一个退出状态码。通常返回 0 表示成功非零值表示错误。
exit 0 # 正常退出
exit 1 # 发生错误
错误处理 错误处理在脚本编写中非常重要。它可以帮助我们捕获并处理错误从而使脚本更加健壮和可靠。 在 Bash 脚本中常用的错误处理方法包括使用 $? 检查命令的退出状态和使用 trap 捕获信号和错误。
使用 $? 检查退出状态 如前所述$? 是一个特殊变量用于获取最近执行命令的退出状态。我们可以通过检查这个状态来判断命令是否成功执行。
#### 示例基本的错误检查#!/bin/bash# 尝试创建一个目录
mkdir my_directory# 检查 mkdir 命令的退出状态
if [ $? -eq 0 ]; thenecho 目录创建成功
elseecho 目录创建失败
fi# 在这个例子中脚本尝试创建一个名为 my_directory 的目录
# 如果 mkdir 命令成功执行输出“目录创建成功”如果失败则输出“目录创建失败”#### 示例在多个命令中使用# 当脚本中有多个命令时可以使用一个函数来集中处理错误#!/bin/basha() {if [ $? -ne 0 ]; thenecho 错误发生在 $1exit 1fi
}# 尝试创建目录
mkdir my_directory
a 创建目录# 尝试移动文件
mv my_file.txt my_directory/
a 移动文件# 在这个例子中check_error 函数检查最近命令的退出状态如果失败则输出错误信息并退出脚本
使用 trap 捕获信号和错误 trap 命令用于捕获信号如 SIGINT即 CtrlC或错误并在捕获到信号时执行指定的命令这对于清理资源或执行特定的错误处理逻辑非常有用。
#### 示例捕获信号#!/bin/bashcleanup() {echo 清理工作...# 这里可以添加清理代码比如删除临时文件等
}# 捕获 SIGINTCtrlC信号
trap cleanup SIGINT# 模拟一个长时间运行的任务
echo 按 CtrlC 退出...
while true; dosleep 1
done# 在这个例子中当用户按下 CtrlC 时cleanup 函数会被调用输出“清理工作...”并执行清理操作#### 示例捕获错误# 我们还可以使用 trap 来捕获脚本中的错误。
# 比如使用 ERR 信号#!/bin/basherror_handler() {echo 发生错误$1exit 1
}# 捕获 ERR 信号
trap error_handler $BASH_COMMAND ERR# 尝试执行一些命令
mkdir my_directory
mv nonexistent_file.txt my_directory/ # 这个命令将失败
echo 这条消息不会被输出# 在这个例子中trap 捕获到任何命令的错误并调用 error_handler 函数输出错误信息并退出脚本 使用 $? 和 trap 是处理 Bash 脚本中错误和异常的有效方法。$? 允许你检查命令的执行状态而 trap 则为你提供了捕获信号和错误处理的能力。通过这些方法我们可以编写出更加健壮和可维护的脚本。
正则表达式 正则表达式是一种用于匹配模式的技巧可以在 Linux 系统中执行文本搜索和替换操作大大提高了工作效率。 下面是一些常用的字符合集。
.匹配任何单个字符?上一项是可选的最多匹配一次*前一项将被匹配零次或多次前一项将被匹配一次或多次{N}上一项完全匹配N次{N,}前一项匹配N次或多次{N,M}前一项至少匹配N次但不超过M次--结束选项标志确保后续参数被视为位置参数^匹配行首的空字符串也代表不在列表范围内的字符$匹配行尾的空字符串\b匹配单词边缘的空字符串\B匹配空字符串前提是它不在单词的边缘\匹配单词开头的空字符串\匹配单词末尾的空字符串
元字符 元字符是表示特殊函数的字符包括 ^ 、$ 、. 、[] 、{} 、- 、? 、* 、 、() 、| 、\\等。除了元字符其他字符在正则表达式中都表示原来的含义。
. # 匹配任意字符但不含空字符
^ # 匹配文本行开头
$ # 匹配文本行结尾 在这个例子里可以看到要注意 ^ 要在前面 $ 要在后面否则操作无效。
方括号 方括号之中的字符表示可以任意匹配其中的一个。 注意元字符放入方括号之中会失去其特殊含义。 但有两种情况除外^ 在方括号的开头表示否定否则只是一个普通字符表示原义。 注意上面命令不会匹配不和 H 或者 h 连在一起包含 e 的字符串因为一个否定的字符集仍然要求存在一个字符。 - 在方括号之中表示一个字符区域。 上面命令匹配所有以大写字母开头的文本行。类似的^[A-Z]、^[a-z]、^[0-9]表示以大写字母、小写字母、数字开头的文本行。上面的[a-Z]则表示所有大写或小写字母 注意连字号如果不构成一个字符区域则表示其本来的含义。比如[a-9]、[-AZ]等
预定义字符类 由于 locale 设置不同Shell展开正则表达式 [A-Z] 时可能不是解释为所有大写字母而是解释为包括所有字母的字典顺序。 为了避免这个问题可以使用正则表达式的预定义字符类。
[:alnum:]字母数字字符在 ASCII 中等价于 [A-Za-z0-9][:word:] 和[:alnum:]相同, 但增加了下划线字符[:alpha:] 字母字符在 ASCII 中等价于 [A-Za-z][:blank:]包含空格和 tab 字符[:cntrl:]ASCII 的控制码包含了0到31和127的 ASCII 字符[:graph:]可视字符在 ASCII 中它包含33到126的字符[:digit:]数字0到9[:lower:]小写字母[:punct:]标点符号字符[:space:] 空白字符包括空格tab回车换行vertical tab, 和 form feed 在 ASCII 中 等价于 [\t\r\n\v\f] [:xdigit:] 用来表示十六进制数字的字符在 ASCII 中等价于 [0-9A-Fa-f][:upper:]大写字母
ls /usr/sbin/[[:upper:]]*
# 上面命令返回所有大写字母开头的文件名
限定符 限定符用于限制匹配的数量下面列出一些常见的限定符。
? # 匹配前面的元素出现0次或1次
* # 匹配前面的元素出现0次或多次# 匹配前面的元素出现1次或多次
{n} # 匹配前面的元素出现了n次
{n,m} # 匹配前面的元素它至少出现了n次但是不多于m次
{n,} # 匹配前面的元素至少出现了n次
{,m} # 匹配前面的元素如果它出现的次数不多于 m 次
文本处理工具
cat 将文件的内容显示在标准输出。
cat 参数 文件名 下面是一些常用参数。
参数作用参数作用参数作用-n显示行号会在输出的每一行前加上行号-b显示行号但只对非空行进行编号-s压缩连续的空行只显示一个空行-E在每一行的末尾显示 $ 符号-T将 Tab 字符显示为 ^I-v显示一些非打印字符 部分效果图如下。 uniq uniq 命令用于检查及删除文本文件中重复出现的行列一般与 sort 命令结合使用。
uniq 参数 文件名 主要参数如下。
参数作用参数作用-c显示每行在文本中重复出现的次数-d设置每个重复记录只出现一次-f跳过对前N个列的比较-D显示所有相邻的重复行-i忽略大小写-s跳过对前N个字符的比较-u仅显示没有重复的记录-w仅对前N个字符进行比较 下面是部分效果图记得先用 sort 排序不然 uniq 只能去除相邻的重复行。 sed sed 命令是利用脚本来处理文本文件。它可以用来对文本进行替换、插入、删除和其他编辑操作。下面介绍具体用法和一些常见示例。
# 基本语法
sed [options] command file# options 用于改变 sed 行为的选项
# command 要执行的操作如替换、删除等
# file 要处理的文件名# 常用选项
# -n 抑制默认输出。只有使用 p 命令时才会输出
# -e 允许在命令行中指定多个 sed 表达式
# -i 直接修改文件而不是输出到标准输出
替换 替换文件中的某个字符串。
sed s/old/new/ filename
# s**: 表示替换操作
# old**: 要被替换的字符串
# new**: 替换成的新字符串# 使用 g 标志替换所有匹配项
sed s/old/new/g filename抑制默认输出 使用 -n 选项可以控制输出结合 p 命令输出匹配的行。
sed -n s/old/new/p filename 这将只输出被替换的行。
删除行 删除特定行或匹配的行。
# 删除第三行
sed 3d filename # 删除包含 one 的行
sed /one/d filename
插入行 在指定行之前插入新行。
sed 2i\This is a new line. filename
# 这将在第二行之前插入 This is a new line.
追加行 在指定行之后追加新行。
sed 2a\This is another new line. filename
# 这将在第二行之后添加 This is another new line.
修改行 替换某一行的内容。
sed 2c\This is the new second line. filename
# 这将把第二行替换为 This is the new second line.
行号范围 可以指定行号范围来执行操作。
# 比如替换第二到第四行中的 old 为 new
sed 2,4s/old/new/g filename
使用正则表达式 sed 支持基本和扩展正则表达式。使用 -E 选项来启用扩展正则表达式。
sed -E s/(a|b)/c/g filename
# 这个命令将 a 或 b 替换为 c
直接修改文件 使用 -i 选项直接修改文件内容。
sed -i s/a/b/g filename
awk awk 是一种处理文本文件的语言是一个强大的文本分析工具。 awk 通过提供编程语言的功能如变量、数学运算、字符串处理等使得对文本文件的分析和操作变得非常灵活和高效。 awk 这个名字是因为取了三位创始人 Alfred AhoPeter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
# 语法
awk options pattern {action} file 主要用到的参数如下。
参数作用参数作用-F 指定字段分隔符-v定义变量-v varvalue 可以在 awk 中使用变量 var-V显示 awk 的版本信息-h显示 awk 的帮助信息包括选项和用法示例 下面是一些常用方法举例。
# 基本示例
# 打印文件的所有行
awk { print } filename# 打印特定字段
# 假设有一个以空格分隔的文件 data.txt内容如下
# Alice 25
# Bob 30
# Charlie 22
#打印第二列年龄
awk { print $2 } data.txt# 使用自定义分隔符
# 如果文件以逗号分隔
# Alice,25
# Bob,30
# Charlie,22
# 使用 -F 指定分隔符
awk -F, { print $1 } data.csv# 条件匹配
# 打印年龄大于 25 的行
awk $2 25 { print } data.txt# 计算总和
# 计算所有年龄的总和
awk { sum $2 } END { print sum } data.txt# 打印行号
# 打印文件的行号和内容
awk { print NR, $0 } data.txt# 内置变量# $0 当前行的完整内容
# $1, $2, ... 当前行的第 1、2、... 列
# NR 当前记录的行号
# NF 当前行的字段数量
# FILENAME 当前文件的名称# 控制结构
# awk 支持控制结构如 if、for 和 while
# if 语句
awk { if ($2 25) print $1 is older than 25. } data.txt# for 循环
# 打印每个字段的值
awk { for (i 1; i NF; i) print $i } data.txt# 函数
# awk 提供了一些内置函数如字符串操作、数学计算等# 字符串函数
# length() 获取字符串长度
awk { print $1, length($1) } data.txt# substr() 获取子字符串
awk { print substr($1, 1, 2) } data.txt# 数学函数
# sqrt() 计算平方根
awk { print $2, sqrt($2) } data.txt# 比如处理 CSV 文件
# 假设有一个 CSV 文件 data.csv内容如下
# Name,Age,Score
# Alice,25,88
# Bob,30,75
# Charlie,22,90
# 打印所有学生的名字和成绩
awk -F, NR 1 { print $1, $3 } data.csv# 组合使用
# awk 可以与其他 Unix 工具结合使用如 grep 和 sort
# 与 grep 结合
grep Alice data.txt | awk { print $2 }# 与 sort 结合
awk { print $2 } data.txt | sort -n
# awk -v 选项用于在执行 awk 命令时定义变量
# 这些变量可以在 awk 脚本中使用以便更灵活地处理数据
# 通过 -v 选项设置的变量可以在模式和操作中使用类似于其他内置变量# 基本语法
awk -v varvalue pattern { action } file
# var 变量的名称
# value 变量的值可以是字符串、数字或表达式# 示例
# 1. 设置简单变量
# 假设有一个文件 data.txt内容如下
# Alice 25
# Bob 30
# Charlie 22
# 要求打印每个人的名字和年龄并在每行前面加上一个固定的前缀
awk -v prefixName: { print prefix, $1, is, $2, years old. } data.txt
# 输出
# Name: Alice is 25 years old.
# Name: Bob is 30 years old.
# Name: Charlie is 22 years old.# 2. 使用变量进行比较
# 我们可以通过 -v 传递一个阈值然后根据这个阈值来过滤数据
awk -v age_limit25 $2 age_limit { print $1 is older than age_limit } data.txt
# 输出
# Bob is older than 25# 3. 计算带变量的总和
# 假设有一个包含多个学生成绩的文件 scores.txt内容如下
# Alice 88
# Bob 75
# Charlie 90
# 我们可以定义一个变量表示额外的分数并计算总分
awk -v extra_points5 { total $2 extra_points; print $1, total score:, total } scores.txt
# 输出
# Alice total score: 93
# Bob total score: 80
# Charlie total score: 95# 4. 结合使用多个变量
# 我们可以同时使用多个变量。例如假设我们想要根据不同的分数阈值进行分类
awk -v pass_score80 -v fail_score60 {if ($2 pass_score) {status Pass} else if ($2 fail_score) {status Fail} else {status Retake}print $1, :, status
} scores.txt
# 输出
# Alice : Pass
# Bob : Fail
# Charlie : Pass# 小结
# 使用 awk -v 可以方便地在脚本中定义和使用变量从而使 awk 脚本更加灵活和易于维护
# 通过将外部变量传递给 awk你可以根据不同的条件和数据动态调整处理逻辑
grep grep 是一个强大的命令行工具用于搜索文本文件中的特定模式或字符串。它支持正则表达式可以用于查找、过滤和处理文本数据。
grep [options] pattern [file...]
# options : 用于改变 grep 行为的选项
# pattern : 要搜索的模式或字符串
# file : 要搜索的文件名。如果不指定文件grep 将从标准输入读取 常用参数如下。
参数作用参数作用-i忽略所有大小写-v反向匹配显示不匹配的行-r递归搜索目录-l只输出包含匹配字符串的文件名-n显示匹配行的行号-c统计匹配行的数量-A n显示匹配行及其后n行-B n显示匹配行及其前n行-C n显示匹配行及其前后各n行-s不显示错误信息 常见用法如下。
基本搜索 搜索文件中包含特定字符串的行。
grep pattern filename 比如查找文件 1.txt 中包含 alice 的行。
grep alice 1.txt 忽略大小写 使用 -i 选项忽略大小写。
grep -i ALICE 1.txt 反向匹配 使用 -v 选项显示不匹配模式的行。
grep -v alice 1.txt 显示行号 使用 -n 选项显示匹配行的行号。
grep -n alice 1.txt 递归搜索 使用 -r 选项递归搜索目录中的文件。
grep -r alice /path/to/directory
只输出文件名 使用 -l 选项只输出包含匹配字符串的文件名。
grep -l alice *.txt 统计匹配行数 使用 -c 选项统计匹配的行数。
grep -c alice 1.txt 显示匹配行及上下文 显示匹配行及其后 n 行。
grep -A 1 alice 1.txt 显示匹配行及其前 n 行。
grep -B 2 alice 1.txt 显示匹配行及其前后各 n 行。
grep -C 1 alice 1.txt 使用正则表达式 grep 支持基本和扩展的正则表达式。使用 -E 选项启用扩展正则表达式。
grep -E alice|bob 1.txt sort sort 是一个用于排序文本文件内容的命令行工具广泛用于 Unix/Linux 系统中。 它可以按字母顺序、数字顺序、时间顺序等对文件中的行进行排序。
# 基本语法
sort [options] [file...]
# options 用于改变 sort 行为的选项
# file 要排序的文件名。如果不指定文件sort 将从标准输入读取 主要参数如下。
参数作用参数作用-n按数字排序-r反向排序从大到小-k知道排序关键字列-t指定字段分隔符-u去重-o将输出写入指定文件-f忽略大小写-M按月份排序 常见用法如下。
基本排序 按字母顺序排序文件的行。
sort filename 数字排序 按数字进行排序而不是按字母。
sort -n 2.txt 反向排序 使用 -r 选项进行反向排序。
sort -r 1.txt 按关键字排序 使用 -k 选项指定排序的列关键字。按第二列年龄排序
sort -k 2 3.txt 指定字段分隔符 使用 -t 选项指定字段分隔符。例如使用逗号作为分隔符
sort -t , -k 2 filename
去重 使用 -u 选项只保留唯一的行。
sort -u 1.txt 输出到文件 使用 -o 选项将结果写入指定文件。
sort 1.txt -o 5.txt cut cut 命令用于从文本文件中提取特定的列或字段。 它可以根据字符位置、字节位置或分隔符来切割文本。
cut [options] [file...] 主要参数如下。
参数作用参数作用-f指定要提取的字段列-d指定字段分隔符默认为制表符-c按字符位置提取-b按字节位置提取 wc wcword count命令用于统计文本文件中的行数、单词数和字节数。
wc [options] [file...] 主要参数如下。
参数作用参数作用-l统计行数-w统计单词数-c统计字节数-m统计字符数 nl nl 命令用于给文本文件的每一行添加行号。它可以方便地查看文本文件的行号。
nl [options] [file...]
# 常用选项
# -b 指定行号的类型a所有行t只对非空行n行号格式
# -w 指定行号的宽度
# -s 指定行号与行内容之间的分隔符 进程管理 管理进程是 Unix/Linux 系统中的一个重要任务涉及到前台和后台进程的控制与查看。 下面将介绍如何管理进程包括查看、控制、启动和停止进程的常用命令。
进程的概念
前台进程 在终端中运行的进程用户可以直接与其交互。前台进程会占用终端直到它结束。
后台进程 在终端中运行但不占用终端的进程。用户可以继续使用终端后台进程在后台运行。
查看进程
ps ps 命令用于查看当前运行的进程。
# 基本用法
ps# 查看所有进程
ps -aux# 查看特定用户的进程
ps -u username# 查看进程树
ps -ejH 不带任何参数时ps 只列出与当前 Session 相关的进程。输出结果中PID 是进程 ID、TTY 是进程的终端号如果显示 ?则表示进程没有终端TIME 是消耗的 CPU 时间CMD 是触发进程的命令。 x 参数列出所有进程的详细信息包括不在当前 Session 的信息。
# 这时的输出结果会多出STAT一栏表示状态
# 它的各种值如下R
# 正在运行或准备运行
S
# 正在睡眠即没有运行正在等待一个事件唤醒
D
# 不可中断睡眠。进程正在等待 I/O比如磁盘驱动器的I/O
T
# 已停止即进程停止运行
Z
# “僵尸”进程。即这是一个已经终止的子进程但父进程还没有清空它没有把子进程从进程表中删除# 高优先级进程。这可能会授予一个进程更多重要的资源给它更多的 CPU 时间
N
# 低优先级进程。一个低优先级进程一个“好”进程只有当其它高优先级进程执行之后才会得到处理器时间 aux 参数可以显示更多信息。
# 输出结果包含的列的含义如下
USER
# 用户ID表示进程的所有者
%CPU
# 百分比表示的 CPU 使用率
%MEM
# 百分比表示的内存使用率
VSZ
# 虚拟内存大小
RSS
# 进程占用的物理内存的大小以千字节为单位
START
# 进程运行的起始时间。若超过24小时则用天表示
top top 命令提供实时的系统监控显示当前运行的进程及其资源使用情况。
top
# 在 top 界面中可以按 q 退出。 它的输出结果分为两部分最上面是系统概要下面是进程列表以 CPU 的使用率排序。 输出结果是动态更新的默认每三分钟更新一次。
htop htop 是 top 命令的增强版提供了更友好的界面和交互功能可以使用方向键选择进程。
htop 控制进程
启动进程 前台进程直接在终端中运行命令。
sleep 60 后台进程在命令后加上 符号。
sleep 60
查看后台进程 使用 jobs 命令查看当前用户的所有后台进程。
jobs
将前台进程放入后台 如果已经在前台运行了一个进程可以使用 Ctrl Z 将其暂停然后使用 bg 命令将其放入后台。
Ctrl Z # 暂停进程
bg # 将其放入后台
将后台进程带回前台 使用 fg 命令将后台进程带回前台。
fg %1 # 带回第一个后台进程 终止进程 使用 kill 命令通过进程 ID (PID) 终止进程。
kill PID 强制终止如果进程不响应可以使用 -9 选项强制终止。
kill -9 PID 通过进程名称终止使用 pkill 命令可以通过进程名称终止进程。
pkill process_name 进阶优化
脚本优化 优化 Linux 脚本的性能和可读性是提升脚本效率和维护性的关键。下面是一些实用的技巧和最佳实践可以帮助在编写和优化脚本时提升性能和可读性。
1、选择合适的解释器 确保使用适合脚本的解释器。 对于 Bash 脚本使用 #!/bin/bash 或 #!/usr/bin/env bash 来确保脚本在正确的环境中运行。
2、使用函数 将重复的代码块封装成函数以提高可读性和可重用性。
3、使用变量 避免重复计算相同的值使用变量存储结果以提高性能。
# 不推荐
for i in $(seq 1 1000); doecho $((i * 2))
done# 推荐
limit1000
for i in $(seq 1 $limit); doecho $((i * 2))
done
4、避免使用外部命令 尽量使用内置命令而不是外部命令因为内置命令的性能通常更好。
# 不推荐
count$(wc -l file.txt)# 推荐
count0
while read -r line; do((count))
done file.txt
5、使用数组 在需要处理多个相关值时使用数组可以提高可读性和性能。
#!/bin/bashfruits(apple banana cherry)
for fruit in ${fruits[]}; doecho $fruit
done
6、使用双引号 在处理字符串时使用双引号以避免意外的单词拆分和路径扩展。
# 不推荐
echo $var# 推荐
echo $var
7、使用条件语句的简洁写法 在处理条件时使用简洁的写法可以提高可读性。
# 不推荐
if [ $var yes ]; thenecho Yes
elseecho No
fi# 推荐
[ $var yes ] echo Yes || echo No
8、性能分析 使用工具如 time、bash -x 或 set -x 来分析脚本的性能和调试信息。
time ./1.sh
9、使用 shellcheck 检查脚本 使用 shellcheck 工具可以帮助你发现脚本中的潜在问题和提高可读性。
# 安装 shellcheck
sudo apt install shellcheck# 检查脚本
shellcheck 1.sh
10、编写文档 在脚本开头添加注释说明脚本的用途、参数和使用方法提高可读性。 通过这些技巧和最佳实践可以有效地优化 Linux 脚本的性能和可读性。优化脚本不仅可以提高执行效率还能使脚本更易于理解和维护。
定时任务 在 Linux 系统中cron 和 at 是两个常用的工具用于设置定时任务。
1、使用 cron 设置定时任务 cron 是一个基于时间的作业调度器可以定期执行任务。
1.1、编辑 cron 任务 要编辑当前用户的 cron 任务可以使用 crontab 命令。
crontab -e这将打开一个文本编辑器我们可以在其中添加定时任务。
1.2、cron 任务的格式
# cron 任务的格式如下* * * * * 命令# 五个星号分别代表从左至右
# 分钟 (0-59)
# 小时 (0-23)
# 日 (1-31)
# 月 (1-12)
# 星期 (0-7)0和7都代表星期日
# 每天凌晨 2 点执行 /path/to/script.sh0 2 * * * /path/to/script.sh# 每小时的第 15 分钟执行 /path/to/script.sh15 * * * * /path/to/script.sh# 每周一的中午 12 点执行 /path/to/script.sh0 12 * * 1 /path/to/script.sh
1.4、查看 cron 任务
crontab -l
1.5、删除 cron 任务
crontab -r # 删除当前用户的所以定时任务
2、使用 at 设置定时任务 at 是一个用于在指定时间执行一次性任务的命令。
2.1 安装 at 在某些 Linux 发行版中at 可能需要单独安装。
sudo yum install at
2.2、启动 atd 服务 在使用 at 之前确保 atd 服务正在运行。
# 启动 atd 服务
sudo systemctl start atd# 设置为开机自启
sudo systemctl enable atd
2.3、使用 at 命令 要使用 at 创建定时任务可以使用以下格式。
at [time]
# 在今天的 15:00 执行 /path/to/script.shecho /path/to/script.sh | at 15:00# 在明天的中午 12:30 执行 /path/to/script.shecho /path/to/script.sh | at 12:30 tomorrow# 在 5 分钟后执行 /path/to/script.shecho /path/to/script.sh | at now 5 minutes
2.5、查看 at 任务
atq
2.6、删除 at 任务 要删除某个 at 任务可以使用 atrm 命令后面跟上任务的 ID可以通过 atq 查看。
atrm job_id
总结 cron 适用于定期执行的任务适合每天、每周或每月执行的作业。 at 适用于一次性任务适合在特定时间执行的作业。
脚本编写 这里编写了几个实用的 Shell 脚本以作参考。
# 备份脚本
# 这个脚本会将指定目录的内容备份到指定的备份目录并在备份文件名中添加时间戳#!/bin/bash# 备份源目录
SOURCE_DIR/path/to/source
# 备份目标目录
BACKUP_DIR/path/to/backup
# 当前日期
CURRENT_DATE$(date %Y%m%d_%H%M%S)# 创建备份
tar -czf $BACKUP_DIR/backup_$CURRENT_DATE.tar.gz -C $SOURCE_DIR .# 输出备份结果
echo Backup of $SOURCE_DIR completed at $CURRENT_DATE.
# 日志分析脚本
# 这个脚本分析 Apache 日志文件统计访问量最多的 IP 地址#!/bin/bash# 日志文件路径
LOG_FILE/var/log/apache2/access.log# 输出结果文件
OUTPUT_FILEtop_ips.txt# 统计 IP 地址并输出到文件
awk {print $1} $LOG_FILE | sort | uniq -c | sort -nr | head -n 10 $OUTPUT_FILE# 输出结果
echo Top 10 IP addresses saved to $OUTPUT_FILE.
# 系统监控脚本
# 这个脚本监控系统的 CPU 使用率和内存使用情况并将结果输出到一个日志文件#!/bin/bash# 日志文件
LOG_FILEsystem_monitor.log# 获取系统信息
CPU_USAGE$(top -bn1 | grep Cpu(s) | sed s/.*, *\([0-9.]*\)%* id.*/\1/ | awk {print 100 - $1})
MEMORY_USAGE$(free | grep Mem | awk {print $3/$2 * 100.0})# 当前日期
CURRENT_DATE$(date %Y-%m-%d %H:%M:%S)# 输出到日志文件
echo $CURRENT_DATE - CPU Usage: $CPU_USAGE% - Memory Usage: $MEMORY_USAGE% $LOG_FILE# 输出结果
echo System monitoring logged to $LOG_FILE.
# 定时清理临时文件脚本
# 这个脚本会定期清理指定目录下的临时文件#!/bin/bash# 临时文件目录
TEMP_DIR/path/to/temp# 删除临时文件
find $TEMP_DIR -type f -mtime 7 -exec rm -f {} \;# 输出结果
echo Temporary files older than 7 days in $TEMP_DIR have been deleted. 个人学习的部分介绍完毕如果有错误希望大家指出谢谢。