Sed正则匹配不支持非贪婪模式

Sed 中正则表达式一个小坑

要把一个监控任务自动化。
监控任务如下:
通过网页查看商品库存数量。如果库存小于阀值,就通知进行补货。

获取网页内容保存本地后。是用下面的脚本获取库存数量

1
cnt=`grep "库存: " html.txt | sed "s/^.*([0-9]+).*$/\1/g"`

商品库存在网页中的格式如下:

1
<b>库存数: 1105</b>  <br/>

结果测试时,打印cnt的值,一直显示为:5

开始百思不得解。

正则表达式没有错啊。

把括号中的部分改为: ([0-9]{4})
这次cnt的值对了:是1105

考虑到库存可能因为销售太快,小于1000,那个就会获取不到。把括号部分改为: ([0-9]{1,4})
重新测试后,发现cnt的值又变为5了。

这下明白了,问题不在括号部分。而在括号的前面的内容。

sed的正则表达式是贪婪匹配模式的。就是说,一个正则模式会尽可能的匹配最大长度。
这里表达式的第一个变长匹配模式为:.因为数字也能匹配”.”, 所以“.”模式不会在第一个数字前停止。会持续匹配,直到后面的内容不能满足匹配,才回退。

所以针对这个例子,我们把sed的正则替换模式修改为:

1
^.*: ([0-9]+).*$

这样,第一个匹配模式在遇到”: “结束。
这样在“: ”后面,”([0-9]+)”模式开始贪婪匹配,匹配出来最长的连续数字,从而获取出正确的库存数。

修改后测试cnt的值为:1105

最后附上自动脚本相关部分的代码

1
2
3
4
5
6
7
8
9
10
11
minute=`date "+%"`
cnt=`cnt=`grep "库存: " html.txt | sed "s/^.*: ([0-9]+).*$/\1/g"``
if [ $cnt -lt 100 ] ; then
if [ $minute -gt 9 -a $minute -lt 10 ]; then #一天只补一次货
echo "补货"
else
echo "非补货时间"
fi
else
echo "货源充足"
fi