Php 函数创建与数字范围匹配的正则表达式
我正在使用Amazon Mechanical TurkAPI,它只允许我使用正则表达式过滤数据字段 我想向函数输入一个整数范围,比如256-311或45-1233,然后返回一个只匹配该范围的正则表达式 匹配256-321的正则表达式是: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
\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,宽度)
返回帕西