# 组合多个字段
echo "luci-base - 2.5.0-1 - 2.5.1-1" | awk '{print $1 " 从 " $3 " 升级到 " $5}'
# 输出:luci-base 从 2.5.0-1 升级到 2.5.1-1
# 使用逗号分隔(AWK会自动添加空格)
echo "luci-base - 2.5.0-1 - 2.5.1-1" | awk '{print $1, "版本变化:", $3, "->", $5}'
# 输出:luci-base 版本变化: 2.5.0-1 -> 2.5.1-1
后者
# 显示字段数量
echo "one two three four five" | awk '{print "字段数:", NF}'
# 输出:字段数: 5
# 显示所有字段
echo "apple banana cherry" | awk '{print "第1个:", $1, "第2个:", $2, "第3个:", $3, "总共:", NF "个字段"}'
# 输出:第1个: apple 第2个: banana 第3个: cherry 总共: 3个字段
# 多行时显示行号
echo -e "第一行\n第二行\n第三行" | awk '{print "第" NR "行:", $0}'
# 输出:
# 第1行: 第一行
# 第2行: 第二行
# 第3行: 第三行
计算
# 简单计算
echo "10 20 30" | awk '{print $1 + $2 + $3}'
# 输出:60
# 平均值计算
echo "10 20 30" | awk '{print "平均值:", ($1 + $2 + $3) / NF}'
# 输出:平均值: 20
# 字符串长度
echo "hello world" | awk '{print "第一个字段长度:", length($1)}'
# 输出:第一个字段长度: 5
好的!我用 echo 结合 cut 来演示 cut 的工作原理:
CUT 基本原理
cut 是一个列提取工具,按指定的分隔符或字符位置来切割文本。
基本语法
bashcut -d '分隔符' -f 字段号
cut -c 字符位置
字段分割演示(-f 参数)
- 基础字段提取
echo -e "apple\tbanana\tcherry" | cut -f 1
# 输出:apple
指定空格为分隔符,提取第1字段
echo "luci-base - 2.5.0-1 - 2.5.1-1" | cut -d ' ' -f 1
# 输出:luci-base
提取第3字段
echo "luci-base - 2.5.0-1 - 2.5.1-1" | cut -d ' ' -f 3
# 输出:2.5.0-1
- 多字段提取
bash# 提取第1和第3字段
echo "apple banana cherry date" | cut -d ' ' -f 1,3
# 输出:apple cherry
提取第1到第3字段
echo "apple banana cherry date" | cut -d ' ' -f 1-3
# 输出:apple banana cherry
提取第2字段到最后
echo "apple banana cherry date" | cut -d ' ' -f 2-
# 输出:banana cherry date
- 不同分隔符演示
bash# 逗号分隔
echo "张三,25,工程师,北京" | cut -d ',' -f 2
# 输出:25
冒号分隔
echo "user:password:1001:1001:User:/home/user:/bin/bash" | cut -d ':' -f 1,6
# 输出:user:/home/user
制表符分隔(默认)
echo -e "name\tage\tcity" | cut -f 2
# 输出:age
字符位置切割演示(-c 参数)
4. 按字符位置提取
bash# 提取第1个字符
echo "hello world" | cut -c 1
# 输出:h
提取第1-5个字符
echo "hello world" | cut -c 1-5
# 输出:hello
提取第7个字符到最后
echo "hello world" | cut -c 7-
# 输出:world
提取多个不连续位置
echo "hello world" | cut -c 1,3,5,7,9
# 输出:hlool
- 实际应用场景
bash# 提取IP地址的第一段
echo "192.168.1.100" | cut -d '.' -f 1
# 输出:192
提取文件扩展名
echo "document.pdf" | cut -d '.' -f 2
# 输出:pdf
提取日期的年份
echo "2024-03-15" | cut -d '-' -f 1
# 输出:2024
多行处理演示
- 批量处理多行
bash# 处理多行数据
echo -e "luci-base - 2.5.0-1 - 2.5.1-1\nkernel - 5.4.188-1 - 5.4.210-1\ndropbear - 2020.81-2 - 2022.82-1" | cut -d ' ' -f 1
# 输出:
# luci-base
# kernel
# dropbear
提取每行的第3和第5字段
echo -e "luci-base - 2.5.0-1 - 2.5.1-1\nkernel - 5.4.188-1 - 5.4.210-1" | cut -d ' ' -f 3,5
# 输出:
# 2.5.0-1 2.5.1-1
# 5.4.188-1 5.4.210-1
CUT 的限制演示
- 处理多个连续空格的问题
bash# 正常情况(单个空格)
echo "apple banana cherry" | cut -d ' ' -f 2
# 输出:banana
问题情况(多个空格)
echo "apple banana cherry" | cut -d ' ' -f 2
输出:(空)
为什么会这样?让我们看看各个字段:
echo "apple banana cherry" | cut -d ' ' -f 1
输出:apple
echo "apple banana cherry" | cut -d ' ' -f 2
输出:(空,因为第2个字段是空格)
echo "apple banana cherry" | cut -d ' ' -f 5
输出:banana(实际在第5个位置)
- 对比 CUT vs AWK 处理空格
bash# 多个空格的情况
text="apple banana cherry"
cut 的处理(有问题)
echo "$text" | cut -d ' ' -f 2
输出:(空)
awk 的处理(正常)
echo "2}'
输出:banana
解释 cut 为什么这样
echo "$text" | cut -d ' ' -f 1-10 --output-delimiter='|'
输出:apple||||banana||||cherry
可以看到多个连续空格被当作多个空字段
字节切割演示(-b 参数)
- 按字节位置
bash# 提取前3个字节
echo "hello" | cut -b 1-3
输出:hel
中文字符处理(UTF-8编码)
echo "你好世界" | cut -b 1-3
输出:你(中文字符占3字节)
echo "你好世界" | cut -c 1-2
输出:你好(按字符数)
实战应用演示
- 系统管理场景
bash# 模拟处理 /etc/passwd 格式
echo "root:x:0:0:root:/root:/bin/bash" | cut -d ':' -f 1,3
输出:root:0
处理CSV格式
echo "张三,28,工程师,50000,北京" | cut -d ',' -f 1,4
输出:张三,50000
提取MAC地址的厂商标识
echo "aa:bb:cc:dd:ee:ff" | cut -d ':' -f 1-3
输出:aa:bb:cc
- 对比原始的 opkg 命令
bash# 模拟 opkg list-upgradable 输出
opkg_output="luci-base - 2.5.0-1 - 2.5.1-1"
使用 cut 提取包名
echo "$opkg_output" | cut -d ' ' -f 1
输出:luci-base
使用 cut 提取当前版本
echo "$opkg_output" | cut -d ' ' -f 3
# 输出:2.5.0-1
使用 cut 提取新版本
echo "$opkg_output" | cut -d ' ' -f 5
# 输出:2.5.1-1
- CUT 的优势和劣势
bash# 优势:简单直接,适合规整格式
echo "name,age,city" | cut -d ',' -f 2 # 简单清晰
劣势:不能处理不规整的空格
echo "name age city" | cut -d ' ' -f 2 # 得到空结果
相比之下 awk 更灵活
echo "name age city" | awk '{print $2}' # 得到 "age"
总结对比
bash# 数据示例
data="luci-base - 2.5.0-1 - 2.5.1-1"
cut: 严格按分隔符切割
echo "$data" | cut -d ' ' -f 1 # luci-base
awk: 智能处理空白字符
echo "$data" | awk '{print $1}' # luci-base