linux expr命令

Linux expr命令用于在命令行中进行表达式求值,支持整数运算、字符串操作、逻辑运算和模式匹配。

提示: expr命令是Shell脚本编程中常用的工具,虽然现在有更多现代替代品(如$(( ))算术扩展),但在兼容性要求高的场景中仍然很有用。

语法格式

expr 表达式
expr [选项] 表达式

操作符和表达式

类别 操作符 说明 示例
算术运算 + 加法 expr 10 + 20
- 减法 expr 30 - 15
\* 乘法(需要转义) expr 5 \* 6
/ 整数除法 expr 20 / 4
% 取模(求余) expr 17 % 5
字符串操作 : 字符串匹配 expr "abcde" : "ab"
length 字符串长度 expr length "hello"
substr 子字符串提取 expr substr "hello" 2 3
index 字符位置查找 expr index "hello" "e"
逻辑运算 & AND运算 expr 1 \& 1
| OR运算 expr 0 \| 1
=, >, <, !=, >=, <= 关系比较 expr 5 \> 3

使用示例

示例1:基本算术运算

# 加法
expr 10 + 20
# 输出:30

# 减法
expr 50 - 25
# 输出:25

# 乘法(注意*需要转义)
expr 6 \* 7
# 输出:42

# 除法(整数除法)
expr 20 / 4
# 输出:5

# 取模
expr 17 % 5
# 输出:2

示例2:字符串长度和匹配

# 获取字符串长度
expr length "hello world"
# 输出:11

# 获取子字符串
expr substr "hello world" 2 5
# 输出:ello

# 查找字符位置
expr index "hello" "e"
# 输出:2

# 字符串匹配(返回匹配的字符数)
expr "hello world" : "hello"
# 输出:5

expr "hello world" : ".*"
# 输出:11(匹配整个字符串)

示例3:逻辑运算

# 关系比较
expr 5 \> 3
# 输出:1(true)

expr 5 \< 3
# 输出:0(false)

expr 5 = 5
# 输出:1

expr 5 != 5
# 输出:0

# AND运算(两者都为真返回1,否则返回第一个操作数)
expr 1 \& 1
# 输出:1

expr 0 \& 1
# 输出:0

# OR运算(第一个为真返回第一个操作数,否则返回第二个操作数)
expr 0 \| 1
# 输出:1

expr 1 \| 0
# 输出:1

示例4:在Shell脚本中使用

#!/bin/bash
# 计算两个数的和
num1=10
num2=20
sum=$(expr $num1 + $num2)
echo "和为: $sum"

# 检查字符串是否以特定前缀开头
str="hello world"
if [ $(expr "$str" : "hello") -gt 0 ]; then
    echo "字符串以'hello'开头"
fi

# 递增计数器
count=0
count=$(expr $count + 1)
echo "当前计数: $count"

示例5:字符串处理

# 提取文件名(不带路径)
fullpath="/home/user/document.txt"
filename=$(expr "$fullpath" : '.*/\(.*\)')
echo "文件名: $filename"

# 提取文件扩展名
filename="document.txt"
extension=$(expr "$filename" : '.*\.\(.*\)')
echo "扩展名: $extension"

# 检查字符串是否包含特定字符
str="hello world"
if [ $(expr index "$str" "o") -gt 0 ]; then
    echo "字符串包含字符'o'"
fi

示例6:实际应用场景

# 计算目录中文件数量
file_count=$(expr $(ls -1 | wc -l) - 1)  # 减1排除可能的"total"行
echo "文件数量: $file_count"

# 生成序列号(结合seq命令的替代方案)
for i in $(seq 1 5); do
    value=$(expr $i \* 10)
    echo "编号$i: $value"
done

# 检查参数是否有效
if [ $(expr "$1" : "[0-9]*$") -gt 0 ]; then
    echo "参数是数字"
else
    echo "参数不是数字"
fi

# 字符串反转(需要复杂处理)
str="hello"
len=$(expr length "$str")
result=""
for i in $(seq $len -1 1); do
    char=$(expr substr "$str" $i 1)
    result="${result}${char}"
done
echo "反转后: $result"

示例7:与现代Shell算术比较

# 传统expr方式
result=$(expr 10 + 20)

# 现代$(( ))方式
result=$((10 + 20))

# 现代let命令
let "result=10+20"

# 现代(( ))命令
((result=10+20))

# 所有方式都得到相同的结果: 30
注意:
  • 操作符与操作数之间必须有空格:expr 1 + 1 而不是 expr 1+1
  • 乘号(*)、大于(>)、小于(<)、与(&)、或(|)等操作符需要转义或加引号
  • expr只支持整数运算,不支持浮点数
  • 除法是整数除法,结果会向下取整
  • expr在比较字符串时,如果比较成功返回1,失败返回0
  • expr在比较数字时,需要转义比较操作符
  • 在现代bash中,建议使用$(( ))进行算术运算,效率更高

expr与现代Shell算术对比

特性 expr $(( )) let
整数运算 支持 支持 支持
浮点数运算 不支持 不支持 不支持
字符串操作 支持 不支持 不支持
模式匹配 支持 不支持 不支持
性能 较慢(外部命令) 快(内置) 快(内置)
可移植性 高(POSIX标准) bash特有 bash特有
语法复杂性 较高(需要转义) 中等

常见错误和解决方案

  • 错误: expr: syntax error
  • 原因: 操作符没有转义或缺少空格
  • 解决: 为*、>、<等操作符添加转义字符
  • 错误: expr: non-integer argument
  • 原因: 使用了非整数参数
  • 解决: 确保参数都是整数

性能优化技巧

  • 对于简单的整数运算,使用$(( ))替代expr
  • 在循环中避免多次调用expr,改用内置算术
  • 将多个expr操作合并为一个
  • 对于字符串操作,expr可能比sed/awk更高效
  • 使用命令替换时注意性能开销
  • 考虑使用awk进行复杂的数值计算

相关命令

  • let - bash内置算术运算命令
  • bc - 任意精度计算器,支持浮点数
  • awk - 强大的文本处理工具,支持数学运算
  • test - 条件测试命令
  • [ ] - test命令的别名
  • sed - 流编辑器,支持字符串操作