上一章我们讲了一半的管道命令,今天把剩下的讲完
1、管道命令
字符转换命令 tr, col, join, paste, expand
1.1 tr
一种可将字符进行替换、压缩、删除,可以将一组字符转换成另一组字符
格式;
tr [-parameter] [string1] [string2]
参数:
参数 | 说明 |
---|---|
-c | 选定字符串1中字符集的补集,即反选字符串1的补集 |
-d | 删除字符串1中出现的所有字符 |
-s | 删除所有重复出现的字符序列,只保留一个 |
**示例:**
# 所有的小写字符r变成大写字符R
ll | tr r R
# -d : 删除字符串1中出现的所有字符
ll | tr -d ':'
1.2 col
该命令是一个标准输入文本过滤器,它从标注输入设备读取文本内容,并把内容显示到标注输出设备
格式
col [-parameter]
参数:
参数 | 说明 |
---|---|
-b | 过滤掉所有的控制字符,包括RLF和HRLF |
-f | 滤除RLF字符,但允许将HRLF字符呈现出来 |
-x | 以多个空格字符来表示跳格字符 |
-l<缓冲区列数> | 预设的内存缓冲区有128列,您可以自行指定缓冲区的大小 |
**示例:**
1.3 join
将两个具有相同域的纪录给挑选出来,再将这些纪录所有的域放到一行(要整合的内容中如有相同的内容,则整合后不会重复显示)
格式
join [-parameter] file1 file2
参数:
参数 | 说明 |
---|---|
-a1或-a2 | 除了显示共同域的纪录之外,-a1显示第一个文件没有共同域的纪录,-a2显示第二个文件中没有共同域的纪录 |
-i | 忽略大小写 |
-o | 设置结果显示的格式 |
-t | 改变域的分隔符 |
-v1或-v2 | 不显示共同域的纪录之外,-v1显示第一个文件没有共同域的纪录,-v2显示第二个文件中没有共同域的纪录 |
-1或-2 | -1用来设置文件1连接的域,-2用来设置文件2连接的域 |
**示例:**
准备工作
将两个具有相同域的纪录给挑选出来,再将这些纪录所有的域放到一行
将join1.txt和join2.txt以:分割 第一个join1.txt取第二个值,第二个join2.txt取第三个进行匹配
1.4 paste
把每个文件以列对列的方式,一列列地加以合并 ,他就是相当于把两个不同的文件内容粘贴在一起,形成新的文件
**格式:**
paste [-parameter] file1 file2
参数:
参数 | 说明 |
---|---|
-d | 默认域的分隔符是空格或tab键,设置新的域分隔符 |
-s | 将每个文件粘贴成一行 |
-- | 从标准输入中读取数据 |
示例
paste join1.txt join2.txt
1.5 expand
转换为空白字符
**格式:**
expand [-parameter]
参数:
参数 | 说明 |
---|---|
-t | 指定制表符所代表的空白字符的个数,而不使用默认的8。 |
-i | 不转换非空白符后的制表符 |
--help | 显示帮助信息 |
--version | 显示版本信息 |
举例:
将当前文件中的数据去掉空格输出到hhh.txt中
2、数据流重定向
-
标准输入in:代码0,使用 < 或者 <<
-
标准输出out:代码1,使用 > 或者 >>
-
错误输出:代码2,使用 > 或者 >>
-
> 表示 写入; >>表示追加
-
<表示 读入;<<表示结束读入
-
2>&1
:2>&1
表示将标准错误输出(stderr)重定向到标准输出(stdout)。command 2>&1
,表示将command
命令的标准错误输出和标准输出合并,并一起显示。
示例
读取运行shell脚本,将错误信息追加到error.log中
2代表的是将错误信息存放入日志内,如果要将正确的信息存放日志内,将2改为1
将错误和正确的信息都放入info.log中
输入内容
3、脚本调试
Shell编程中,调试是一个重要的环节,它帮助我们查找脚本中的问题并进行修复。同时,合理的错误处理也是编写健壮的Shell脚本的关键 。可以理解为java中的断点调试,可以清晰的看出是如何运行的
3.1 调试工具和技巧
在我们的shell脚本中,我们使用echo命令时,其实我们错过了一些中间结果,比如赋值,我们时看不到的,为了我们打印时可以看到变量,我们使用一下断点调试
我们根本不清楚变量是什么变量
set -x
使用set -x
命令可以在脚本执行过程中显示每个命令及其参数,非常有助于查看脚本的执行流程
只要加入我们的set -x就可以进行文本调试,
对我们的代码是有侵入性的,所以我们还有一种方式来调试
调试器:bash -x
如果脚本比较复杂,使用上述方法可能不够方便。我们可以通过在终端中运行脚本,并加上-x
选项来调试整个脚本,首先需要讲set -x删除掉
set -e
使用set -e
命令可以在脚本执行过程中,一旦出现非零返回值的命令,立即退出脚本。这对于快速发现错误非常有帮助。
程序出错时,停止往下运行,直接终止、
示例:
我们有一个函数,在运行脚本时调用这个文件,然后打印执行结果
结果
我们打印的 add方法的调用结果是没有进行打印,因为我们程序出错了,立刻进行停止了
原来是这样的,我们先讲set -e注释掉
结果
3.2 错误处理
在Shell脚本中,错误处理是确保脚本在运行过程中能够适当地处理各种异常情况的关键
检查命令返回值
在脚本中执行命令后,可以通过$?
变量来获取命令的返回值。通常,返回值为0表示命令成功执行,非零值表示命令执行失败。
我们查看当前/path/to/non_existent_dir下的文件,很显然我们是没有这个文件的,所以$?是不等于0的,$?等于零说明我们的命令是正确的,我们进行if判断,判断上一个命令是不等于0的,不等于0就打印一句话
我们下节课会将流程控制语句
#!/bin/bash
ls /path/to/non_existent_dir
if [ $? -ne 0 ]; then
echo "Error: Directory not found."
fi
当我们上一句命令找不到当前文件就会打印错误
我们换成可以存在的路径
使用exit命令退出脚本
在脚本中,如果发现错误或者异常情况,可以使用exit
命令终止脚本的执行,并返回一个非零值表示错误
判断如果不是文件,则返回 1 ,通过$?来获取当前的返回的状态
使用trap命令捕获信号
使用trap
命令可以捕获脚本接收到的信号,并执行相应的操作。这样可以在脚本执行过程中优雅地处理中断。
以下是 trap
命令的十种主要用法及其代码示例:
*用法* | *示例代码* |
---|---|
捕获并处理指定信号 | trap 'echo "Signal received."' INT |
忽略指定信号 | trap '' TERM |
恢复默认的信号处理方式 | trap - INT |
设置 EXIT 信号处理函数 | trap 'cleanup' EXIT |
在函数内部设置 RETURN 信号处理函数 | func() { trap 'cleanup' RETURN; ... } |
清除所有已设置的信号处理函数 | trap - INT TERM EXIT |
执行命令并在结束时恢复先前的信号处理方式 | trap 'cmd' EXIT; cmd |
在循环中使用 trap 避免在接收到信号时终止循环 | while true; do trap 'break' INT; ... ; done |
使用函数作为信号处理函数 | trap 'cleanup' INT; cleanup() { echo "Cleaning up..."; } |
处理多个信号 | trap 'echo "Signal 1 received."' SIGUSR1; trap 'echo "Signal 2 received."' SIGUSR2 |
清理资源
当这个shell脚本执行完毕之后,进行清理工作
记录错误日志
故意使用一个错误的命令,我们的trap会捕捉到移除,然后将错误信息打印到日志内
忽略特定信号
当我们使用Ctrl+c的时候,会打印一句,并终止脚本
优雅处理脚本终止
首先我们有清理操作,这个无论如何都会执行,还有我们的Running script,代码逻辑.我们传入一个error参数,就会执行错误的打印,并返回1 不打印成功,如果我们不传入error参数,就不会走打印错误的信息
我们没有传入error,所以先执行业务处理,成功之后,我们清理数据
我们传入error,所以先执行业务处理,失败之后,我们清理数据
CentOS 7(以及大多数类Unix/Linux系统)中,信号是进程间通信的一种方式,用于通知进程某个事件的发生。这些信号具有预定义的编号和名称,并且大多数系统信号在POSIX标准中都有定义。以下是一些CentOS 7中常用的信号列表,这些信号可以通过kill命令或其他方式发送给进程:信号编号信号名称描述 SIGHUP 终端挂起或用户退出。常用于通知进程重新读取配置文件并重启。 SIGINT 中断信号,通常由Ctrl+C产生,要求进程立即停止。 SIGQUIT 退出信号,生成core dump后退出。 SIGABRT 由abort()函数产生,导致程序异常终止。 SIGKILL 强制杀死进程,该信号不能被捕获、阻塞或忽略。 SIGALRM 定时器超时。 SIGTERM 请求程序终止。这是kill命令的默认信号,可以被捕获、阻塞或忽略。 SIGCONT 如果进程已停止(例如,收到SIGSTOP信号),则继续执行。 SIGSTOP 停止进程的执行,不能被捕获、阻塞或忽略。 SIGTSTP 终端停止信号,通常由Ctrl+Z产生。 注意:这个列表并不包含所有可用的信号,只是列出了一些常用的信号。信号编号和名称在大多数Unix和类Unix系统中都是相同的,因为它们遵循POSIX标准。你可以使用kill -l命令在CentOS 7中查看所有可用的信号及其编号和名称。此外,还有一些实时信号(实时信号编号通常从34开始),但这些信号在日常使用中相对较少见,主要用于需要高精度控制的场景。对于大多数用户和应用程序来说,上述列出的信号已经足够使用。