我已经完成了这个(在 PHP 中):
class Converter
{
const REGEXP_OR = '|';
const REGEXP_START = '^';
const REGEXP_END = '$';
protected $sStart;
protected $sEnd;
function __construct($mStart, $mEnd=null)
{
if(is_array($mStart) && count($mStart)>1)
{
$this->sStart = (string)($mStart[0]);
$this->sEnd = (string)($mStart[1]);
}
else
{
$this->sStart = (string)($mStart);
$this->sEnd = (string)($mEnd);
}
if((int)($mStart)>(int)($mEnd))
{
$this->sStart = $this->sEnd = null;
}
}
public function getRegexp()
{
return self::REGEXP_START.$this->_get_regexp_by_range($this->sStart, $this->sEnd).self::REGEXP_END;
}
protected function _get_regexp_by_range($sStart, $sEnd, $sOr=self::REGEXP_OR, $sFrom=self::REGEXP_START, $sTill=self::REGEXP_END)
{
if(!isset($sStart) || !isset($sEnd))
{
return null;
}
if((int)($sStart)>(int)($sEnd))
{
return null;
}
elseif($sStart==$sEnd)
{
return $sStart;
}
elseif(strlen($sEnd)>strlen($sStart))
{
$rgRegexp = array($this->_get_regexp_by_range($sStart, str_repeat('9', strlen($sStart))));
for($i=strlen($sStart)+1; $i<strlen($sEnd)-1; $i++)
{
$rgRegexp[] = $this->_get_regexp_by_range('1'.str_repeat('0', $i), str_repeat('9', $i+1));
}
$rgRegexp[] = $this->_get_regexp_by_range('1'.str_repeat('0', strlen($sEnd)-1), $sEnd);
return join($sTill.$sOr.$sFrom, $rgRegexp);
}
else
{
$rgRegexp = array();
for($iIntersect=0;$iIntersect<strlen($sStart);$iIntersect++)
{
if($sStart[$iIntersect]!=$sEnd[$iIntersect])
{
break;
}
}
if($iIntersect)
{
return join($sTill.$sOr.$sFrom, array_map(function($sItem) use ($iIntersect, $sStart)
{
return substr($sStart, 0, $iIntersect).$sItem;
}, explode($sTill.$sOr.$sFrom, $this->_get_regexp_by_range(substr($sStart, $iIntersect), substr($sEnd, $iIntersect)))));
}
else
{
$rgRegexp = array($sStart);
for($iPos=strlen($sStart)-1; $iPos>0; $iPos--)
{
if($sStart[$iPos]+1<10)
{
$rgRegexp[]=substr($sStart, 0, $iPos).'['.($sStart[$iPos]+1).'-'.'9'.']'.str_repeat('[0-9]', strlen($sStart)-$iPos-1);
}
}
if(($sStart[0]+1)<($sEnd[0]-1))
{
$rgRegexp[]='['.($sStart[0]+1).'-'.($sEnd[0]-1).']'.str_repeat('[0-9]', strlen($sStart)-1);
}
elseif((int)($sStart[0])+1==(int)($sEnd[0])-1)
{
$rgRegexp[]=($sStart[0]+1).str_repeat('[0-9]', strlen($sStart)-1);
}
for($iPos=1; $iPos<strlen($sEnd); $iPos++)
{
if($sEnd[$iPos]-1>=0)
{
$rgRegexp[]=substr($sEnd,0, $iPos).'['.'0'.'-'.($sEnd[$iPos]-1).']'.str_repeat('[0-9]', strlen($sEnd)-$iPos-1);
}
}
$rgRegexp[]=$sEnd;
return join($sTill.$sOr.$sFrom, $rgRegexp);
}
}
}
}
然后,它使用任何字符串都能得到正确的结果,但我认为生成的正则表达式不是最好的。
$sPattern = (new Converter('1', '1000000000'))->getRegexp();
var_dump(
preg_match('/'.$sPattern.'/', '10000000000'),
preg_match('/'.$sPattern.'/', '100000000'));
无论如何,非常感谢所有回答的人。