shell脚本中常用指令数据处理
shell脚本的介绍
shell脚本的介绍
Shell脚本的核心确实是 “命令的组合” + “逻辑控制(判断/循环)” + “熟练的操作经验”。为了让之前的复习更扎实,把整体的结构做成结构化脑图。
🧠 Shell 脚本核心知识图谱
1. 基石:指令的熟练操作(你提到的重点)
脚本的本质是“批处理”,所以对单个指令的熟悉程度决定脚本质量。
文件操作:
ls、cp、mv、rm、mkdir、touch。文本处理(重中之重):
grep(过滤)、sed(流编辑)、awk(列处理)、wc(统计)、sort(排序)。系统状态:
ps(进程)、netstat/ss(端口)、df/du(磁盘)。神器:
xargs(参数传递)、find(查找文件)。2. 骨架:变量与参数
脚本不能写死,需要靠变量传递值。
自定义变量:
a=10(注意=两边不能有空格)。系统变量:
$HOME、$PATH、$PWD。位置参数:
$0(脚本名)、$1~$9(第1~9个参数)、$#(参数个数)、$?(上一条命令执行结果,0为成功)。命令替换:
date赋值给变量 =>d=$(date)或d=date。3. 灵魂:判断与循环(逻辑控制)
这是脚本从“顺序执行”变为“智能执行”的关键。
(1)条件判断(
if和case) 判断的核心是[ 条件 ](注意空格),本质上执行的是test命令。
文件判断:
-f(是否存在且为文件)、-d(目录)、-e(是否存在)、-x(可执行)。数值比较(只能用整数):
-eq(等于)、-ne(不等于)、-gt(大于)、-lt(小于)、-ge(≥)、-le(≤)。
易错点:
>和<是字符串比较,别用在数字上!字符串比较:
=(相等)、!=(不等)、-z(为空)。
匹配关键词自动显示为彩色
临时设置:
# alias grep='grep --color=auto' //只针对当前终端和当前用户生效
永久设置:
1)全局(针对所有用户生效)
vim /etc/bashrc
alias grep='grep --color=auto'
source /etc/bashrc
2)局部(针对具体的某个用户)
vim ~/.bashrc
alias grep='grep --color=auto'
注意:如果希望你对环境变量的设置立刻生效,可以使用以下命令而不需要重启计算机
source ~/.bashrc数据处理方式
shell脚本数据的处理
1)数据检索:grep tr cut
2)数据处理:uniq sort tee paste xargs
awk的应用场景
1)字符串截取
2)数据运算
3)比如内存使用率脚本行检索:grep / egrep
grep 基本检索(案例演示及参数介绍)
# 在日志中查找包含 "error" 的行(不区分大小写)
grep -i "error" /var/log/syslog
# 查找不包含 "debug" 的行
grep -v "debug" app.log
# 递归查找当前目录下所有 .conf 文件中包含 "AllowOverride" 的行
grep -r "AllowOverride" /etc/apache2/*.conf
# 显示匹配行及其上下各2行
grep -C 2 "timeout" nginx.log
# 忽略大小写匹配包含root的行
grep -i "root" /etc/passwd
# 精确匹配ftp单词
grep -w "ftp" /etc/passwd
# 打印匹配到的关键字ftp
grep -wo "ftp" /etc/passwd
# 打印匹配到root关键字的行号
grep -n "root" /etc/passwd
# 忽略大小写匹配并显示包含关键字root的行
grep -ni "root" /etc/passwd
# 忽略大小写匹配并统计包含关键字root的行数
grep -nic "root" /etc/passwd
# 忽略大小写匹配以root开头的行
grep -i "^root" /etc/passwd
# 匹配以bash结尾的行
grep "bash$" /etc/passwd
# 匹配空行并打印行号
grep -n "^$" /etc/passwd
# 匹配以#号开头的行
grep "^#" /etc/vsftpd/vsftpd.conf
# 匹配不以#号开头的行
grep -v "^#" /etc/vsftpd/vsftpd.conf
# 匹配包含mail关键字及其后5行
grep -A 5 "mail" /etc/passwd
# 匹配包含mail关键字及其前5行
grep -B 5 "mail" /etc/passwd
# 匹配包含mail关键字及其前后各5行
grep -C 5 "mail" /etc/passwd
# 参数介绍
-i: 不区分大小写
-v: 查找不包含指定内容的行,反向选择
-w: 按单词搜索
-n: 显示行号
-A: 显示匹配行及后面多少行 -A 5
-B: 显示匹配行及前面多少行
-o: 打印匹配关键字
-c: 统计匹配到的次数
-r: 逐层遍历目录查找
-C: 显示匹配行前后多少行
-l:只列出匹配的文件名
-L:列出不匹配的文件名
-e: 使用正则匹配
-E:使用扩展正则匹配
^key:以关键字开头
key$:以关键字结尾
^$:匹配空行
--color=auto :可以将找到的关键词部分加上颜色的显示egrep(扩展正则)
# 查找包含 error 或 warning 的行
egrep "error|warning" /var/log/nginx/access.log
# 查找以数字开头的行
egrep "^[0-9]" data.txt
# 查找包含连续3个以上数字的行
egrep "[0-9]{3,}" user_list.txt
# 查找以 error 或 warning 开头的行
egrep "^(error|warning)" /var/log/syslog
# 查找包含邮箱地址的行
egrep "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" contacts.txt
# 查找包含 IP 地址的行
egrep "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log
# 查找空行或只有空格的行
egrep "^[[:space:]]*$" config.conf
# 查找以 a、b 或 c 开头的行
egrep "^[abc]" wordlist.txt
# 参数介绍
egrep: 等同于 grep -E,支持扩展正则表达式
|: 或,匹配多个模式之一
^: 匹配行首
$: 匹配行尾
[0-9]: 匹配任意数字
[a-zA-Z]: 匹配任意字母
{n,}: 匹配前面字符至少 n 次
{n,m}: 匹配前面字符 n 到 m 次
+: 匹配前面字符至少 1 次
*: 匹配前面字符 0 次或多次
?: 匹配前面字符 0 次或 1 次
\.: 转义,匹配点号
[[:space:]]: 匹配空白字符(空格、制表符等)
(): 分组,将多个模式视为一个整体字符串检索:cut / tr
cut — 按列/字符裁剪
# 提取 /etc/passwd 的用户名(第1列,以:分隔)
cut -d: -f1 /etc/passwd | head -5
# 提取文件的第3到第5个字符
cut -c3-5 file.txt
# 提取第1列和第3列,以逗号分隔输出
cut -d, -f1,3 data.csv
# 以:冒号分割,截取第1列内容
cut -d: -f1 1.txt
# 以:冒号分割,截取第1,6,7列内容
cut -d: -f1,6,7 1.txt
# 截取文件中每行第4个字符
cut -c4 1.txt
# 截取文件中每行的1-4个字符
cut -c1-4 1.txt
# 截取文件中每行的4-10个字符
cut -c4-10 1.txt
# 从第5个字符开始截取后面所有字符
cut -c5- 1.txt
# 参数介绍
cut: 用于列截取
-c: 以字符为单位进行分割
-d: 自定义分隔符,默认为制表符 \t
-f: 与 -d 一起使用,指定显示哪个区域tr — 字符替换/删除
# 将所有小写字母转为大写
echo "hello world" | tr 'a-z' 'A-Z'
# 删除所有数字
echo "abc123def456" | tr -d '0-9'
# 压缩连续的换行符为一个换行符
cat messy.txt | tr -s '\n'
# 将文件中的逗号全部替换为制表符
cat data.csv | tr ',' '\t' > data.tsv
# 删除所有空格
echo "hello world" | tr -d ' '
# 将冒号替换为制表符
echo "root:x:0:0" | tr ':' '\t'
# 将大写字母转为小写
echo "HELLO WORLD" | tr 'A-Z' 'a-z'
# 删除所有标点符号
echo "hello,world!@#" | tr -d '[:punct:]'
# 压缩连续的空格为一个空格
echo "hello world" | tr -s ' '
# 参数介绍
tr: 用于字符转换、删除和压缩
-d: 删除指定字符
-s: 压缩连续重复字符为一个字符
'a-z' 'A-Z': 将小写字母转换为大写字母
'0-9': 匹配所有数字
'\n': 换行符
'\t': 制表符
' ': 空格
'[:punct:]': 匹配所有标点符号
数据处理命令
sort — 数据排序
# 按数字排序(默认是字典序)
sort -n numbers.txt
# 按第2列(数值)排序,:分隔
sort -t: -k2 -n /etc/passwd | head -5
# 逆序排序
sort -r -n scores.txt
# 按第3列排序,且忽略前导空格
sort -k3 -b data.txt
# 按第2列数值排序,然后按第1列字母排序
sort -t, -k2,2n -k1,1 data.csv
# 对文件去重排序
sort -u data.txt
# 按第二列字母逆序排序
sort -t: -k2 -r /etc/passwd
# 按月份排序(Jan, Feb, Mar...)
sort -M month.txt
# 按第三列数值排序并忽略大小写
sort -t: -k3 -n -f /etc/passwd
# 检查文件是否已排序
sort -c data.txt
# 参数介绍
sort: 文本排序
-n: 按数值排序(默认是字典序)
-r: 逆序排序
-t: 指定字段分隔符(默认是空白)
-k: 指定排序字段(列),如 -k2 按第2列排序
-u: 去重排序(等同于 sort | uniq)
-b: 忽略前导空格
-M: 按月份排序(Jan, Feb, Mar...)
-f: 忽略大小写
-c: 检查文件是否已排序,未排序则报错
-k2,2n: 指定第2列为起始结束,按数值排序
uniq — 数据去重(通常与 sort 配合)
# 去除连续重复行
uniq 2.txt
# 只显示重复的行
uniq -d 2.txt
# 统计重复行出现的次数
uniq -dc 2.txt
# 统计重复行出现的次数
sort access.log | uniq -c
# 只显示重复的行
sort list.txt | uniq -d
# 只显示不重复的行
sort list.txt | uniq -u
# 统计每个IP的访问次数(去重统计并降序排列)
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# 参数介绍
uniq: 用于去除连续重复行(通常与 sort 配合使用)
-i: 忽略大小写
-c: 统计重复行出现的次数
-d: 只显示重复的行
-u: 只显示不重复的行paste — 文本数据合并
# 横向合并两个文件(按行并列)
paste file1.txt file2.txt
# 使用指定分隔符合并
paste -d: names.txt emails.txt
# 将文件的所有行合并成一行(类似转置)
paste -s -d, scores.txt
# 合并多个列,输出为CSV
paste -d, col1.txt col2.txt col3.txt > merged.csvtee — 数据输出分流
# 同时显示并保存到文件(覆盖)
echo "System info" | tee info.txt
# 追加到文件
date | tee -a log.txt
# 管道中间使用:统计行数并保存原始数据
grep "ERROR" app.log | tee error.log | wc -l
# 同时写入两个文件
ls -l | tee file1.txt file2.txtxargs — 参数传递与批量处理
# 查找所有 .log 文件并删除
find /var/log -name "*.log" -type f | xargs rm -f
# 批量创建用户(从 user.txt 读用户名)
cat users.txt | xargs -I {} useradd -m {}
# 并行执行(4个进程)
cat urls.txt | xargs -P 4 -I {} curl -s {} > /dev/null
# 将每5个参数作为一组执行
echo 1 2 3 4 5 6 7 8 | xargs -n 3 echo "组:"
# 交互式确认删除
find . -name "*.tmp" | xargs -p rmshell字符
有基础的同学不要和正则表达式中的符号含义搞混淆了。
!: 执行历史命令 !! 执行上一条命令
$: 变量中取内容符
+ - * / %: 对应数学运算 加 减 乘 除 取余数
&: 后台执行
;: 分号可以在shell中一行执行多个命令,命令之间用分号分割
\: 转义字符
``: 反引号 命令中执行命令 echo "today is `date +%F`"
' ': 单引号,脚本中字符串要用单引号引起来,但是不同于双引号的是,单引号不解释变量
" ": 双引号,脚本中出现的字符串可以用双引号引起来
通配符
~: 家目录 # cd ~ 代表进入用户家目录
*: 星号是shell中的通配符 匹配所有
?: 问号是shell中的通配符 匹配除回车以外的一个字符
[list]: 匹配[list]中的任意单个字符
[!list]: 匹配除list中的任意单个字符
{string1,string2,...}: 匹配string1,string2或更多字符串
重定向
> 覆盖输入
>> 追加输入
< 输出
<< 追加输出
管道命令
|: 管道符 上一个命令的输出作为下一个命令的输入 cat filename | grep "abc"
原创
shell脚本中常用指令数据处理
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法