expr命令全解

expr(expression 的缩写)是 Linux/Unix 系统中一款经典的命令行工具,主要用于整数运算、字符串处理和逻辑判断。它通过命令行参数接收表达式,计算并输出结果,常被用于 shell 脚本中处理简单的数值和字符串操作。本文将从基础语法到高级用法,全面解析 expr 命令的功能与实践。

一、expr 基本语法与特性

1. 语法格式

expr 的核心语法非常简单,通过空格分隔表达式的各个元素:
expr 表达式
 
其中,“表达式” 可以是整数运算(如 1 + 2)、字符串操作(如 length "hello")或逻辑判断(如 5 > 3)。

2. 核心特性

  • 无交互模式:所有操作通过命令行参数完成,无交互式输入;
  • 返回值规则:
    • 计算成功时,输出表达式结果(整数或字符串);
    • 计算失败时(如语法错误、运算不成立),输出空值,且返回状态码非 0(可通过 $? 查看);
  • 适用场景:shell 脚本中处理简单运算、字符串长度计算、模式匹配等轻量任务。

二、整数运算:最常用的核心功能

expr 支持基本的整数算术运算,包括加、减、乘、除、取余,运算符号前后必须有空格(否则会被视为字符串)。

1. 加法(+)

expr 10 + 5  # 输出:15
expr 2 + -3  # 支持负数,输出:-1
 

2. 减法(-)

expr 10 - 5  # 输出:5
expr 5 - 10  # 输出:-5
 

3. 乘法(*)

注意:* 在 shell 中是通配符,必须用反斜杠 \ 转义:
expr 10 \* 5  # 输出:50
expr 3 \* -2  # 输出:-6
 

4. 除法(/)

仅支持整数除法,结果向下取整(截断小数部分):
expr 10 / 3   # 输出:3(10÷3=3.333,截断为3)
expr 7 / 2    # 输出:3
expr -10 / 3  # 输出:-3(向下取整)
 

5. 取余(%)

返回除法的余数(结果符号与被除数一致):
expr 10 % 3   # 输出:1(10 = 3×3 + 1)
expr 7 % 2    # 输出:1
expr -10 % 3  # 输出:-1(-10 = 3×(-4) + (-1))
 

三、字符串操作:处理文本的实用功能

expr 提供了简单的字符串处理能力,包括计算长度、查找字符位置、模式匹配等,适合轻量文本处理场景。

1. 计算字符串长度(length)

expr length "hello"        # 输出:5("hello"有5个字符)
expr length "hello world"  # 输出:11(包含空格)
 

2. 查找字符在字符串中首次出现的位置(index)

expr index "字符串" "字符集":返回 “字符集” 中任意字符在 “字符串” 中首次出现的位置(从 1 开始计数,无匹配则返回 0)。
expr index "hello" "l"     # 输出:3("l"在"hello"中首次出现在第3位)
expr index "hello" "aeiou" # 输出:2(元音字母"e"在第2位)
expr index "hello" "xyz"   # 输出:0(无匹配字符)
 
注意:index 匹配的是 “字符集中的任意单个字符”,而非字符串整体。

3. 字符串模式匹配(match 或 :)

用于判断字符串是否匹配指定模式(支持基础正则表达式),返回匹配的长度(无匹配则返回 0)。两种语法等价:
expr match "字符串" "模式"
expr "字符串" : "模式"
 

常用示例:

# 匹配以"he"开头的字符串,返回匹配长度
expr match "hello" "he"       # 输出:2
expr "hello" : "he"           # 输出:2

# 匹配数字开头的字符串(正则 \([0-9]\+\) 捕获数字)
expr "123abc" : "\([0-9]\+\)" # 输出:3(匹配"123",长度3)
expr "abc123" : "\([0-9]\+\)" # 输出:0(非数字开头,无匹配)

# 匹配任意字符(. 表示任意单字符,* 表示前面字符出现0次或多次)
expr "test.txt" : "test.*"    # 输出:8("test.txt"整体匹配,长度8)
 
说明:模式中的 \(` 和 `\) 用于捕获匹配的子串(仅返回捕获部分的长度),无捕获时返回整个匹配的长度。

4. 提取子字符串(substr)

expr substr "字符串" 起始位置 长度:从 “起始位置”(从 1 开始)提取指定 “长度” 的子串。
expr substr "hello world" 1 5   # 输出:hello(从第1位开始,取5个字符)
expr substr "hello world" 7 5   # 输出:world(从第7位开始,取5个字符)
expr substr "hello" 3 2         # 输出:ll(从第3位开始,取2个字符)
 

四、逻辑判断:比较与条件验证

expr 可进行整数或字符串的比较运算,返回1(真) 或0(假),常与 shell 条件语句(如 if)结合使用。

1. 整数比较

运算符含义示例(返回 1 为真,0 为假)
= 等于 expr 5 = 5 → 1;expr 5 = 3 → 0
!= 不等于 expr 5 != 3 → 1;expr 5 !=5→0
> 大于 expr 5 > 3 → 1;expr 3 >5→0
< 小于 expr 3 < 5 → 1;expr 5 <3→0
>= 大于等于 expr 5 >=5 →1;expr 3 >=5→0
<= 小于等于 expr 3 <=5 →1;expr 5 <=3→0
注意:< 和 > 在 shell 中是重定向符号,必须用反斜杠 \ 转义:
expr 5 \> 3  # 输出:1(5>3为真)
expr 3 \< 5  # 输出:1(3<5为真)
 

2. 字符串比较

字符串比较仅支持 =(等于)和 !=(不等于),按字符 ASCII 码逐位比较:
expr "abc" = "abc"   # 输出:1(相等)
expr "abc" = "abd"   # 输出:0(不相等)
expr "abc" != "def"  # 输出:1(不相等)
 

3. 在 shell 脚本中结合条件判断

#!/bin/bash
a=10
b=5

# 判断 a 是否大于 b
if [ $(expr $a \> $b) -eq 1 ]; then
  echo "$a 大于 $b"
else
  echo "$a 不大于 $b"
fi
# 输出:10 大于 5
 

五、实战场景:expr 命令的典型用法

1. 脚本中简单的数值计算

#!/bin/bash
# 计算两个数的和、差、积、商
read -p "输入第一个数:" num1
read -p "输入第二个数:" num2

sum=$(expr $num1 + $num2)
diff=$(expr $num1 - $num2)
prod=$(expr $num1 \* $num2)
quotient=$(expr $num1 / $num2)

echo "和:$sum"
echo "差:$diff"
echo "积:$prod"
echo "商:$quotient"
 

2. 验证输入是否为纯数字

利用模式匹配判断字符串是否全为数字:
#!/bin/bash
read -p "请输入一个数字:" input

# 匹配纯数字(^ 表示开头,$ 表示结尾,[0-9]\+ 表示1个以上数字)
if [ $(expr "$input" : "^[0-9]\+$") -gt 0 ]; then
  echo "输入是纯数字"
else
  echo "输入不是纯数字"
fi
 

3. 提取文件名与扩展名

#!/bin/bash
file="document.txt"

# 提取文件名(不包含扩展名)
filename=$(expr "$file" : "\(.*\)\.")
# 提取扩展名
extension=$(expr "$file" : ".*\(\..*\)")

echo "文件名:$filename"   # 输出:document
echo "扩展名:$extension" # 输出:.txt
 

六、注意事项与局限性

1. 必须注意的语法细节

  • 运算符前后必须有空格:expr 1+2 会被视为字符串 “1+2”,返回错误;正确写法是 expr 1 + 2
  • 特殊字符需转义:*()<> 等在 shell 中有特殊含义,必须用 \ 转义(如 \*\<)。
  • 字符串含空格需加引号:如 expr length "hello world",不加引号会被解析为多个参数,导致错误。

2. 局限性

  • 不支持浮点数运算:expr 仅能处理整数,浮点数计算需用 bc 或 awk(如 echo "2.5 + 3.5" | bc)。
  • 正则表达式支持有限:仅支持基础正则(如 *+[]),不支持扩展正则(如 ?() 分组)。
  • 性能较低:复杂运算或大量数据处理时,效率远低于 awk 或 Python 脚本。

posted on 2025-10-07 13:24  coding博客  阅读(20)  评论(0)    收藏  举报