问题描述
我正在使用 Amazon Mechanical Turk API,它只允许我使用正则表达式来过滤数据字段.
I am working with the Amazon Mechanical Turk API and it will only allow me to use regular expressions to filter a field of data.
我想向函数输入一个整数范围,例如 256-311 或 45-1233,并返回一个仅匹配该范围的正则表达式.
I would like to input an integer range to a function, such as 256-311 or 45-1233, and return a regex that would match only that range.
匹配 256-321 的正则表达式将是:
A regex matching 256-321 would be:
((25[6-9])|(2[6-9][0-9])|(3[0-1][0-9])|(32[0-1]))
这部分相当简单,但我在创建这个正则表达式的循环时遇到了麻烦.
That part is fairly easy, but I am having trouble with the loop to create this regex.
我正在尝试构建一个这样定义的函数:
I am trying to build a function defined like this:
function getRangeRegex( int fromInt, int toInt)
{
return regexString;
}
我浏览了整个网络,我很惊讶过去似乎没有人解决过这个问题.这是一个难题……
I looked all over the web and I am surprised that it doesn't look like anyone has solved this in the past. It is a difficult problem...
感谢您的宝贵时间.
推荐答案
这里有一个快速破解:
<?php
function regex_range($from, $to) {
if($from < 0 || $to < 0) {
throw new Exception("Negative values not supported");
}
if($from > $to) {
throw new Exception("Invalid range $from..$to, from > to");
}
$ranges = array($from);
$increment = 1;
$next = $from;
$higher = true;
while(true) {
$next += $increment;
if($next + $increment > $to) {
if($next <= $to) {
$ranges[] = $next;
}
$increment /= 10;
$higher = false;
}
else if($next % ($increment*10) === 0) {
$ranges[] = $next;
$increment = $higher ? $increment*10 : $increment/10;
}
if(!$higher && $increment < 10) {
break;
}
}
$ranges[] = $to + 1;
$regex = '/^(?:';
for($i = 0; $i < sizeof($ranges) - 1; $i++) {
$str_from = (string)($ranges[$i]);
$str_to = (string)($ranges[$i + 1] - 1);
for($j = 0; $j < strlen($str_from); $j++) {
if($str_from[$j] == $str_to[$j]) {
$regex .= $str_from[$j];
}
else {
$regex .= "[" . $str_from[$j] . "-" . $str_to[$j] . "]";
}
}
$regex .= "|";
}
return substr($regex, 0, strlen($regex)-1) . ')$/';
}
function test($from, $to) {
try {
printf("%-10s %s
", $from . '-' . $to, regex_range($from, $to));
} catch (Exception $e) {
echo $e->getMessage() . "
";
}
}
test(2, 8);
test(5, 35);
test(5, 100);
test(12, 1234);
test(123, 123);
test(256, 321);
test(256, 257);
test(180, 195);
test(2,1);
test(-2,4);
?>
产生:
2-8 /^(?:[2-7]|8)$/
5-35 /^(?:[5-9]|[1-2][0-9]|3[0-5])$/
5-100 /^(?:[5-9]|[1-9][0-9]|100)$/
12-1234 /^(?:1[2-9]|[2-9][0-9]|[1-9][0-9][0-9]|1[0-2][0-3][0-4])$/
123-123 /^(?:123)$/
256-321 /^(?:25[6-9]|2[6-9][0-9]|3[0-2][0-1])$/
256-257 /^(?:256|257)$/
180-195 /^(?:18[0-9]|19[0-5])$/
Invalid range 2..1, from > to
Negative values not supported
未经适当测试,使用风险自负!
Not properly tested, use at your own risk!
是的,生成的正则表达式在许多情况下可以写得更紧凑,但我把它留给读者作为练习:)
And yes, the generated regex could be written more compact in many cases, but I leave that as an exercise for the reader :)
这篇关于创建匹配数字范围的正则表达式的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!