Php 函数创建与数字范围匹配的正则表达式

Php 函数创建与数字范围匹配的正则表达式,php,regex,function,integer,range,Php,Regex,Function,Integer,Range,我正在使用Amazon Mechanical TurkAPI,它只允许我使用正则表达式过滤数据字段 我想向函数输入一个整数范围,比如256-311或45-1233,然后返回一个只匹配该范围的正则表达式 匹配256-321的正则表达式是: \b((25[6-9])|(2[6-9][0-9])|(3[0-1][0-9])|(32[0-1]))\b 这一部分相当简单,但是我在创建这个正则表达式的循环中遇到了麻烦 我正在尝试构建一个定义如下的函数: function getRangeRegex( in

我正在使用Amazon Mechanical TurkAPI,它只允许我使用正则表达式过滤数据字段

我想向函数输入一个整数范围,比如256-311或45-1233,然后返回一个只匹配该范围的正则表达式

匹配256-321的正则表达式是:

\b((25[6-9])|(2[6-9][0-9])|(3[0-1][0-9])|(32[0-1]))\b
这一部分相当简单,但是我在创建这个正则表达式的循环中遇到了麻烦

我正在尝试构建一个定义如下的函数:

function getRangeRegex( int fromInt, int toInt)
{

      return regexString;
}
if ($number >= 256 && $number <= 321){
   // do something 
}
我浏览了整个网络,我很惊讶,过去似乎没有人解决过这个问题。这是一个难题


谢谢您的时间。

是否有理由使用regex?不能做这样的事情:

function getRangeRegex( int fromInt, int toInt)
{

      return regexString;
}
if ($number >= 256 && $number <= 321){
   // do something 
}

这实际上已经完成了

看看这个网站。它包含一个指向python脚本的链接,该脚本可以自动为您生成这些正则表达式。

这里有一个快速破解:


产生:

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])$/
无效的范围2..1,从>到
不支持负值
未经适当测试,使用风险自负


是的,生成的正则表达式在很多情况下都可以编写得更紧凑,但我把它留给读者作为练习:)

对于像我一样,正在寻找上面伟大的@Bart Kiers作品的javascript版本的人来说

//Credit: Bart Kiers 2011
function regex_range(from, to){
        if(from < 0 || to < 0) {
            //throw new Exception("Negative values not supported"); 
            return null;
        }
        if(from > to) {
            //throw new Exception("Invalid range from..to, from > to"); 
            return null;
        }

        var ranges = [];
        ranges.push(from);
        var increment = 1;
        var next = from;
        var higher = true;

        while(true){
            next += increment;
            if(next + increment > to) {
                if(next <= to) {
                    ranges.push(next);
                }
                increment /= 10;
                higher = false;
            }else{ 
                if(next % (increment*10) == 0) {
                    ranges.push(next);
                    increment = higher ? increment*10 : increment/10;
                }
            }

            if(!higher && increment < 10) {
                break;
            }
        }

        ranges.push(to + 1);
        var regex = '/^(?:';

        for(var i = 0; i < ranges.length - 1; i++) {
            var str_from = ranges[i];
            str_from = str_from.toString();
            var str_to = ranges[i + 1] - 1;
            str_to = str_to.toString();
            for(var j = 0; j < str_from.length; j++) {
                if(str_from[j] == str_to[j]) {
                    regex += str_from[j];
                }
                else {
                    regex += "[" + str_from[j] + "-" + str_to[j] + "]";
                }
            }
            regex += "|";
        }

        return regex.substr(0, regex.length - 1 ) + ')$/';
    }
//来源:巴特·基尔斯2011
函数regex_范围(从,到){
如果(从<0 | |到<0){
//抛出新异常(“不支持负值”);
返回null;
}
如果(从>到){
//抛出新异常(“无效范围从..到,从>到”);
返回null;
}
var范围=[];
射程。推(从);
var增量=1;
var next=从;
var较高=真实;
while(true){
下一个+=增量;
如果(下一步+增量>到){
如果(next这个答案是从中复制的。我也把它做成了一个


使用正则表达式验证数值范围

需要明确的是:什么时候一个简单的if语句就足够了

if(num < -2055  ||  num > 2055)  {
   throw  new IllegalArgumentException("num (" + num + ") must be between -2055 and 2055");
}
为了避免与
8215242
内部的
15
匹配,单词边界是必需的

两位数范围

规则:数字必须介于

15
16
之间。三个可能的正则表达式:

\b(15|16)\b
\b1(5|6)\b
\b1[5-6]\b
数字范围“镜像”在零附近

规则:数字必须介于

-12
12

这里有一个从

0
12
的正则表达式,只有正值:

\b(\d|1[0-2])\b

自由间距:

\b(         //The beginning of a word (or number), followed by either
   \d       //   Any digit 0 through 9
|           //Or
   1[0-2]   //   A 1 followed by any digit between 0 and 2.
)\b         //The end of a word
   (?<!-)          //Something not preceded by a dash
   \b(             //Word-start, followed by either
      [1-3]?       //   No digit, or the digit 1, 2, or 3
         \d{1,2}   //   Followed by one or two digits (between 0 and 9)
   |               //Or
      400          //   The number 400
   )\b             //Word-end
   -?                 //Optional dash
   \b(                //Followed by word boundary, followed by either of the following
      20(             //   "20", followed by either
         5[0-5]       //      A "5" followed by a digit 0-5
      |               //   or
         [0-4][0-9]   //      A digit 0-4, followed by any digit
      )
   |                  //OR
      1?[0-9]{1,3}    //   An optional "1", followed by one through three digits (0-9)
   )\b                //Followed by a word boundary.

无论是负数还是正数,只要在开始处添加一个可选的破折号就可以了:

-?\b(\d|1[0-2])\b
(假设破折号前没有不合适的字符。)

要禁止使用负数,必须使用负数查找:

(?<!-)\b(\d|1[0-2])\b

自由间距:

\b(         //The beginning of a word (or number), followed by either
   \d       //   Any digit 0 through 9
|           //Or
   1[0-2]   //   A 1 followed by any digit between 0 and 2.
)\b         //The end of a word
   (?<!-)          //Something not preceded by a dash
   \b(             //Word-start, followed by either
      [1-3]?       //   No digit, or the digit 1, 2, or 3
         \d{1,2}   //   Followed by one or two digits (between 0 and 9)
   |               //Or
      400          //   The number 400
   )\b             //Word-end
   -?                 //Optional dash
   \b(                //Followed by word boundary, followed by either of the following
      20(             //   "20", followed by either
         5[0-5]       //      A "5" followed by a digit 0-5
      |               //   or
         [0-4][0-9]   //      A digit 0-4, followed by any digit
      )
   |                  //OR
      1?[0-9]{1,3}    //   An optional "1", followed by one through three digits (0-9)
   )\b                //Followed by a word boundary.
最后一个示例:四位数字,镜像在零附近,不以零结尾

规则:必须介于

-2055
2055

这是来自堆栈溢出。

正则表达式:

-?\b(20(5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b

自由间距:

\b(         //The beginning of a word (or number), followed by either
   \d       //   Any digit 0 through 9
|           //Or
   1[0-2]   //   A 1 followed by any digit between 0 and 2.
)\b         //The end of a word
   (?<!-)          //Something not preceded by a dash
   \b(             //Word-start, followed by either
      [1-3]?       //   No digit, or the digit 1, 2, or 3
         \d{1,2}   //   Followed by one or two digits (between 0 and 9)
   |               //Or
      400          //   The number 400
   )\b             //Word-end
   -?                 //Optional dash
   \b(                //Followed by word boundary, followed by either of the following
      20(             //   "20", followed by either
         5[0-5]       //      A "5" followed by a digit 0-5
      |               //   or
         [0-4][0-9]   //      A digit 0-4, followed by any digit
      )
   |                  //OR
      1?[0-9]{1,3}    //   An optional "1", followed by one through three digits (0-9)
   )\b                //Followed by a word boundary.

下面是这个正则表达式的一个可视化表示:

在这里,您可以自己试一试:

(感谢on stackoverflow提供的调试帮助。)

最后说明

根据您的身份,可能所有子组都应划分为非捕获组。例如:

(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b)
-?\b(20(5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b

而不是这个:

(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b)
-?\b(20(5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b
示例Java实现


我把Bart Kiers的答案转换成C++。函数以两个整数作为输入,并生成数字范围的正则表达式。

#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>

std::string regex_range(int from, int to);

int main(int argc, char **argv)
{
    std::string regex = regex_range(1,100);

    std::cout << regex << std::endl;

    return 0;
}

std::string regex_range(int from, int to) //Credit: Bart Kiers 2011
{
    if(from < 0 || to < 0)
    {
        std::cout << "Negative values not supported. Exiting." << std::endl;
        return 0;
    }

    if(from > to)
    {
        std::cout << "Invalid range, from > to. Exiting." << std::endl;
        return 0;
    }

    std::vector<int> ranges;
    ranges.push_back(from);
    int increment = 1;
    int next = from;
    bool higher = true;

    while(true)
    {

        next += increment;

        if(next + increment > to)
        {
            if(next <= to)
            {
                ranges.push_back(next);
            }
            increment /= 10;
            higher = false;
        }
        else if(next % (increment*10) == 0)
        {
            ranges.push_back(next);
            increment = higher ? increment*10 : increment/10;
        }

        if(!higher && (increment < 10))
        {
            break;
        }
    }

    ranges.push_back(to + 1);
    std::string regex("^(?:");

    for(int i = 0; i < ranges.size() - 1; i++)
    {
        int current_from = ranges.at(i);
        std::string str_from = std::to_string(current_from);
        int current_to = ranges.at(i + 1) - 1;
        std::string str_to = std::to_string(current_to);
        for(int j = 0; j < str_from.length(); j++)
        {
            if(str_from.at(j) == str_to.at(j))
            {
                std::string str_from_at_j(&str_from.at(j));
                regex.append(str_from_at_j);
            }
            else
            {
                std::string str_from_at_j(&str_from.at(j));
                std::string str_to_at_j(&str_to.at(j));

                regex.append("[");
                regex.append(str_from_at_j);
                regex.append("-");
                regex.append(str_to_at_j);
                regex.append("]");
            }
        }
        regex.append("|");
    }
    regex = regex.substr(0, regex.length() - 1);
    regex.append(")$");
    return regex;
}
#包括
#包括
#包括
#包括
std::string regex_范围(int-from,int-to);
int main(int argc,字符**argv)
{
std::string regex=regex_范围(1100);

std::cout小心,卓越的@Bart Kiers代码(以及Travis J的JS版本)在某些情况下会失败。例如:

12-1234    /^(?:1[2-9]|[2-9][0-9]|[1-9][0-9][0-9]|1[0-2][0-3][0-4])$/
与“1229”、“1115”、“1[0-2][0-2][5-9]”的PHP端口不匹配

由于我已经有了与@EmilianoT相同的问题,我试图修复它,但最后我选择了移植of(由@EmilianoT移植),虽然不是在类中。我对这个JS端口不太满意,因为所有
toString()
parseInt()
方法仍然可以优化(它们可能不必要),但它适用于所有情况

我更改的是参数。我将
parse($min,$max,$MatchWholeWord=FALSE,$MatchWholeLine=FALSE,$MatchLeadingZero=FALSE)
替换为
parse(min,max,width=0,prefix='',suffix='')
,这给了它更多的选项(有些人可能想把正则表达式放在斜杠上,有些人想匹配行)[
prefix='^';suffix='$'
]等)。我还希望能够配置数字的宽度(
width=3
→ <代码>000
001
052
800
1000
,…)

我替换了我以前的答案,因为它并不总是有效。如果你想阅读它,他们可以在答案历史中看到它

函数解析(最小值、最大值、宽度=0、前缀=''、后缀=''){
如果(!Number.isInteger(min)| |!Number.isInteger(max)| | min>max | | min<0 | | max<0){
返回错误
}
如果(最小值==最大值){
返回parseIntoPattern(最小值、前缀、后缀)
}
设x=parseStartRange(最小,最大)
让s=[]
x、 forEach(o=>{
s、 推送(parseEndRange(o[0],o[1]))
})
设n=reformatArray(s)
设h=parseIntoRegex(n,宽度)
返回帕西