Shell 脚本截取字符串指定位置内容,优先使用 Shell 内置变量扩展语法,处理文本流时简单列提取用 cut,复杂逻辑或不定分隔符用 awk。
先说结论:变量内部截取用 Shell 原生语法,管道流处理简单分隔符用 cut,复杂文本分析用 awk。
- 适合:变量操作选${var:pos:len},固定分隔符选 cut,灵活匹配选 awk。
- 重点看:cut 默认分隔符为制表符,awk 默认支持空格和制表符。
- 别忽略:多字节字符环境下 cut -b 按字节截取可能导致乱码,需用 cut -c。
命令速用版
直接复制以下命令到终端测试,根据数据源类型选择对应方案。
# 1. Shell 变量内部截取(最快,无需子进程)
var="Hello World"
echo ${var:0:5} # 输出:Hello
echo ${var:6:5} # 输出:World
# 2. cut 命令截取(适合固定分隔符)
echo "a:b:c" | cut -d ':' -f 2 # 输出:b
echo "12345" | cut -c 2-4 # 输出:234
# 3. awk 命令截取(适合复杂逻辑)
echo "a:b:c" | awk -F ':' '{print $2}' # 输出:b
echo "123 456" | awk '{print substr($0,2,3)}' # 输出:23 为什么会这样
cut 是外部命令专为列提取设计,awk 是文本处理语言支持逻辑判断,Shell 变量扩展是内置功能无进程开销。
cut 命令设计初衷是快速剪切文本文件的列,默认依赖制表符分隔,对空格分隔支持较差,需要指定 -d 参数。awk 默认将连续空格或制表符视为分隔符,更适合处理人类可读的日志或非标准化数据。Shell 内置变量扩展 ${var:offset:length} 直接在当前 Shell 进程内存中操作,无需创建子进程,因此在脚本循环中性能最优。
分步处理
按照数据源类型选择工具,先确认分隔符特征,再编写对应命令,最后验证输出。
1. 确认数据源类型:如果是脚本内变量,直接使用 ${var:start:length} 语法,起始位置从 0 开始计数。如果是管道传递的文本流,检查分隔符是否固定。
2. 选择截取工具:分隔符固定且单一(如冒号、逗号)使用 cut -d 'sep' -f N。分隔符不固定或需要条件判断(如打印满足特定值的列)使用 awk -F 'sep' '{print $N}'。
3. 处理多字节字符:涉及中文或非 ASCII 字符时,cut 命令避免使用 -b 参数(按字节),改用 -c 参数(按字符),防止截断半个汉字导致乱码。
怎么验证是否生效
使用 echo 构造测试数据,对比预期输出与实际输出,检查是否有多余空格或换行。
执行命令后观察终端输出,若使用 cut 或 awk 处理文件,可用 head -n 1 预览第一行结果。对于变量截取,使用 echo "$var" 确认内容未丢失。若结果包含意外换行,检查命令末尾是否有多余 echo 或 print 换行符。
常见坑
cut 默认分隔符是制表符而非空格,awk 字段编号从 1 开始而 Shell 变量索引从 0 开始。
很多用户误以为 cut -d ' ' 能完美处理多个连续空格,实际上 cut 会将每个空格视为分隔符产生空字段,此时应改用 awk。另外,Shell 变量截取 ${var:0:5} 中长度不足时不会报错,只返回剩余内容,需确保逻辑兼容。
常见问题
cut 和 awk 处理空格分隔有什么区别?
cut 将每个空格视为独立分隔符,awk 将连续空格视为一个分隔符。
Shell 变量截取索引从 0 还是 1 开始?
Shell 变量截取 ${var:start:length} 索引从 0 开始,awk 字段 $1 从 1 开始。
如何截取字符串最后几个字符?
使用 Shell 变量扩展 ${var:0-n},其中 n 为倒数字符数,如 ${var:0-5} 截取最后 5 个字符。
参考来源
- linux 中 shell,awk,sed 截取字符串方法总结
- Shell:字符串的分割截取 - 龙雪 - 博客园
- shell 如何截取字符串
- 如何在 Shell 脚本中实现字符串的截取和拼接?
- 【Shell】shell 截取字符串方式 (cut、awk、sed 命令)
- [Shell] 字符截取命令:cut, printf, awk, sed
- Linux 学习 8 之 Shell 编程--字符截取命令 (cut、printf、awk、sed) - 透明的千纸鹤 - 博客园
- shell 脚本提取字符串的几种方式
- shell 编程——字符截取和替换命令