Convert integer numeric interval to regex

后端 未结 3 1215
轻奢々
轻奢々 2020-12-06 21:48

SO,

I\'m looking for a solution about the problem - how to convert integer interval to regex. Suppose I have two numbers, A and B. Both of

3条回答
  •  清歌不尽
    2020-12-06 22:42

    I've done with this (in 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_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_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=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);
              }
           }
        }
    }
    

    then, it get correct results with any strings, but I think the resulting regex is not the best one.

    $sPattern = (new Converter('1', '1000000000'))->getRegexp();
    var_dump(
       preg_match('/'.$sPattern.'/', '10000000000'), 
       preg_match('/'.$sPattern.'/', '100000000'));
    

    anyway, thanks a lot to all who answered.

提交回复
热议问题