文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>expr用法

expr用法

时间:2007-12-19  来源:061107

17.5 expr用法
expr命令一般用于整数值,但也可用于字符串。一般格式为:
expr argument operator argument
expr也是一个手工命令行计数器。
$expr 10 + 10
20
$expr 1500 + 900
2500
$expr 30 / 3
10
$expr 30 / 3 / 2
5
(注意运算符左右都有空格)
使用乘号时,必须用反斜线屏蔽其特定含义。因为shell可能会误解显示星号的意义。
$expr 30 * 3
90

17.5.1 增量计数
expr在循环中用于增量计算。首先,循环初始化为0,然后循环值加1,反引号的用法意
即替代命令。最基本的一种是从(expr)命令接受输出并将之放入循环变量。
$LOOP=0
$LOOP=`expr $LOOP + 1`

17.5.2 数值测试
可以用expr测试一个数。如果试图计算非整数,将返回错误。
$rr=1.1
$expr $rr + 1
expr: non-numeric argument
$rr=2
$expr $rr + 1
3
(注意:这个例子与原文不同)
这里需要将一个值赋予变量(不管其内容如何),进行数值运算,并将输出导入dev/null,
然后测试最后命令状态,如果为0,证明这是一个数,其他则表明为非数值。
$value=12
$expr $value + 10 > /dev/null 2>&1
$echo $?
0
这是一个数。
$value=hello
$expr $value + 10 > /dev/null 2>&1
$echo $?
2
这是一个非数值字符。

expr也可以返回其本身的退出状态,不幸的是返回值与系统最后退出命令刚好相反,成
功返回1,任何其他值为无效或错误。下面的例子测试两个字符串是否相等,这里字符串为
“hello”和“hello”。
$value=hello
$expr $value = "hello"
1
$echo $?
0
expr返回1。不要混淆了,这表明成功。现在检验其最后退出状态,返回0表示测试成功,
“hello”确实等于“hello”。

17.5.3 模式匹配
expr也有模式匹配功能。可以使用expr通过指定冒号选项计算字符串中字符数。.*意即任
何字符重复0次或多次。
$value=accounts.doc
$expr $value : '.*'
12

在expr中可以使用字符串匹配操作,这里使用模式. d o c抽取文件附属名。
$expr $value : '(.*).doc'
accounts
=============================

请问各位大虾:shell 中有数组吗?

当然有,用
$varname[0]=value1
$varname[1]=value2
....
来定义

$echo ${varname[0]}
方式来引用
      论正则表达式的“贪婪”性   正则表达式是具有贪婪性的,我们从下面这例谈起:
已知str="uid=100(guest) gid=100(others) groups=10(users),11(floppy)"
现在想要得到这个字符串中的第一个括号内的值,即guest该怎么办?假设$str的括号外的内容是不固定的,不能依据uid之类的关键字或空格去查找,所依据的只能是找第一对括号内的内容。

很自然的我们想到用sed,因为sed具有很强的模式匹配的功能,而且能够将匹配的部分内容强行记下来用于输出。这样,我们就会想:
echo $str|sed 's/模式串/1/'
只要模式串写好了,在匹配的过程中把guest这个字符串抠出来,让sed记住,然后用1输出就可以了。怎么写这个模式串?
.*想要匹配"uid=100"
(...)告诉sed要查找括弧内的文本
(.*)让sed记住匹配内容的常用手段,这里匹配的.*将来就能用1取出来
.*想要匹配" gid=100(others) groups=10(users),11(floppy)"部分
于是我们就写成了echo $str|sed 's/.*((.*)).*/1/'
结果呢,得到的是"floppy",为什么?
正则表达式是有贪婪性的,它总是与最长的可能长度匹配,而且越是排在前面的通配符优先级越高。这一例,第一个.*可以匹配"uid=100(guest) gid=100(others) groups=10(users),11",仍然能保证后面通配符的匹配,那一对()匹配了floppy左右的括号,最后的.*自然是可有可无的,所以sed记住的就是floppy。
怎么办?我们必须打破正则表达式的贪吃性,用更明确的描述来实现这一点:
我们考虑如果在模式串中第一个.*中告诉sed这个.*是不能含有"("的,不久可以将.*限制到"uid=100"了吗?这个意思我们完全可以用[^(]*来表达,于是我们修订刚才的代码,变成:
echo $str|sed 's/[^(]*((.*)).*/1/'
似乎应该很好了,执行的结果却是"guest) gid=100(others) groups=10(users),11(floppy",为什么?
原来仍然是正则表达是的贪婪性在作怪,虽然我们有效的阻止了第一个.*的贪吃,但是我们对(.*)中的.*却未加限制,于是它尽可能匹配了"guest) gid=100(others) groups=10(users),11(floppy",还能保证后面".*"的匹配性。我们再作限制,告诉sed,(.*)中的.*不能含有"",让它跨不过guest:
echo $str|sed 's/[^(]*(([^)]*)).*/1/'
这回,输出结果终于是我们想要得"guest"了。

问题解决了,我们也了解了正则表达式(或说通配符)的贪婪性,于是就可以留个问题给大家,让大家自己体会体会:
怎么样取出str中第二对括号的内容"others"?
怎么样取出str中第三对括号的内容"users"?
怎么样取出str中第四对括号的内容"floppy"?(这个还用说吗,就利用正则表达式的贪婪性,我们最开始不就实现它了嘛)
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载