Bash中提取的数字含特殊字符无法作整数使用,如何去除?
这问题我碰到过不少——那些看不见的ANSI终端控制字符在搞鬼!从你用printf '%q'输出的'\E[?25h\E[?0c20'就能看出来,提取到的字符串前面带着终端控制序列(用来控制光标显示、终端状态的非打印字符),这些字符肉眼看不到,但会彻底干扰数值运算和命令参数解析。
下面给你几种简单有效的解决方法:
方法1:用sed过滤掉所有非数字字符
直接保留字符串里的0-9数字,其他所有字符(包括控制字符)全部删除:
result=$(./my_script | awk '{print $4}' | sed 's/[^0-9]//g')
解释:s/[^0-9]//g是sed的替换规则,[^0-9]匹配任何不是数字的字符,//g表示全局替换为空,最终只留下纯数字。
方法2:用tr快速删除非数字字符
tr工具更适合做字符过滤的简单场景,效果和sed一致:
result=$(./my_script | awk '{print $4}' | tr -cd '0-9')
解释:-c表示取字符集的补集,-d表示删除指定字符,所以tr -cd '0-9'就是删除所有不是0-9的字符,只保留数字。
方法3:用awk一步到位提取数字(推荐)
不用先取字段再处理,直接从原始输出里匹配连续数字,避免控制字符和数字在同一个字段里的问题:
result=$(./my_script | awk '{match($0, /[0-9]+/, num); print num[0]}')
解释:match($0, /[0-9]+/, num)会在整行文本中匹配最长的连续数字序列,把结果存在num数组里,num[0]就是我们要的纯数字。
方法4:精准删除ANSI控制序列
如果你确定干扰字符都是ANSI转义序列(格式通常是ESC[开头,跟着数字/分号,最后以字母结尾),可以精准删除这类序列:
result=$(./my_script | awk '{print $4}' | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g')
解释:\x1b是ESC字符的十六进制表示,\[[0-9;]*[a-zA-Z]匹配标准的ANSI控制序列格式,把这些序列全部清除,剩下的就是干净的数字。
验证方法
处理完后,再用printf '%q' $result检查,输出应该只有20(没有转义的控制字符),这时再执行result=$((result+1))或者seq 0 $result就不会报错了。
内容的提问来源于stack exchange,提问作者Tutankhamen

