php - 创建匹配数字范围的正则表达式的函数

标签 php regex function integer range

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

我想向函数输入一个整数范围,例如 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;
}

我浏览了整个网络,令我惊讶的是过去似乎没有人解决过这个问题。这是一个难题...

感谢您的宝贵时间。

最佳答案

这是一个快速的技巧:

<?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\n", $from . '-' . $to, regex_range($from, $to));
  } catch (Exception $e) {
    echo $e->getMessage() . "\n";
  }
}

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

未经适当测试,使用风险自负!

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

关于php - 创建匹配数字范围的正则表达式的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6710236/

相关文章:

regex - 我想打印两个文件之间的差异和共同点,并以特定输入文件的相同顺序打印结果

java - 如何将输出写入文本文件,与 show() 函数显示的输出相同

php - file_get_contents ('php://input' ) 总是返回一个空字符串

java - 不同 tomcat 日志条目的正则表达式模式

java - 将字节数组从 PHP 发送到 Java Socket

ruby-on-rails - 如何将整个单词与 Aho corasick 匹配?

function - '不兼容类型 : IntRange and Int' error in Kotlin

c++ - 程序可以编译,但分解成函数后实际上并不能移动电机

javascript - jquery post表单具有多个同名字段

php - 字段 'xxx' 没有默认值