Bash脚本中如何将文件读取的字符串数字转为整数并判断大小?
我来帮你搞定这个问题——你碰到的integer expression expected报错,主要是两个原因:要么是文件里的行包含隐藏的非数字字符,要么是脚本里的语法用错了。咱们一步步来分析和解决:
先搞清楚你之前的脚本哪里错了
1. 原始脚本的语法问题
你写的if [ 'expr $line /1' -gt 80 ]这里有个致命错误:单引号会把里面的内容原样输出,所以'expr $line /1'不会执行expr命令,而是直接把这个字符串当成要比较的"值",自然和80没法做整数比较,直接报错。
就算你改成双引号,[ "expr $line /1" -gt 80 ]也不对,因为你需要的是执行expr的结果,应该用命令替换$(expr "$line" / 1),但expr本身对非数字很敏感,而且不如bash内置的算术运算好用。
2. 为什么val=$(($line + 0))还是报错?
大概率是你的文件里的行有隐藏字符,比如Windows格式的换行符\r(用cat -A temp1可以看到行尾的^M)。如果某行是81\r,那么$line的值就是81\r,$((line + 0))会因为\r不是数字而报错。
正确的解决方案
第一步:清理文件的隐藏字符
先检查文件是否有Windows换行符或其他非数字字符:
cat -A temp1
如果看到行尾有^M,说明是Windows格式,转成Unix格式:
# 方法1:用dos2unix(如果已安装) dos2unix temp1 # 方法2:用sed手动去掉回车符 sed -i 's/\r$//' temp1
第二步:用Bash内置的算术表达式做判断
Bash的(( ... ))语法支持直接的整数运算和比较,而且会自动把纯数字字符串转成整数,比expr或[ -gt ]更可靠。
给你一个修正后的完整脚本:
#!/bin/bash file=/root/temp1 # 先清理可能的Windows换行符(可选,但建议加上) sed -i 's/\r$//' "$file" while IFS= read -r line do # 先校验行是否是纯整数,避免非数字行报错 if [[ "$line" =~ ^[0-9]+$ ]]; then # 用(( ... ))做整数比较,简洁又可靠 if (( line > 80 )); then echo "hit>80: $line" fi else echo "Warning: 行内容 '$line' 不是有效的整数" fi done <"$file"
其他可选的写法
如果不想用(( ... )),也可以用[[ ... ]]配合-gt,但前提是变量是纯数字:
if [[ "$line" -gt 80 ]]; then echo "hit>80" fi
不过这种写法如果遇到非数字字符还是会报错,所以加上纯数字校验更稳妥。
总结一下
- 先确保文件里的每行都是纯数字,没有隐藏的回车、空格或其他字符;
- 优先用Bash内置的
(( ... ))语法做整数比较,比expr更高效、更不容易出错; - 加上纯数字校验可以避免脚本遇到非数字行时崩溃。
内容的提问来源于stack exchange,提问作者Michele Pardini

