40

我正在寻找生成随机/唯一字符串的最短方法,为此我使用了以下两个:

$cClass = sha1(time());

或者

$cClass = md5(time());

但是,我需要字符串以字母开头,我正在查看 base64 编码,但==最后添加了它,然后我需要摆脱它。

用一行代码实现这一目标的最佳方法是什么?


更新:

PRNDL 提出了一个很好的建议,我最终使用了它,但做了一些修改

echo substr(str_shuffle(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ),0, 1) . substr(str_shuffle(aBcEeFgHiJkLmNoPqRstUvWxYz0123456789),0, 31)

会产生 32 个模仿 md5 哈希的字符,但它总是会产生第一个字符一个字母,就像这样;

解决方案 1

但是,Uours确实改进了他的回答;

substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1).substr(md5(time()),1);

更短更甜

Anonymous2011的另一个建议非常棒,但由于某种原因,第一个字符总是 M、N、Y、Z,所以不符合我的目的,但会是选择的答案,顺便说一句,有谁知道为什么它总是产生那些特定的字母?

这是我修改版本的预览

echo  rtrim(base64_encode(md5(microtime())),"=");

亚军

4

17 回答 17

30

与其打乱字母字符串,不如得到一个随机字符更快。

从字符串中获取单个随机字符,然后将其附加md5( time( ) )到它。在附加之前md5( time( ) )从中删除一个字符,以便将生成的字符串长度保持为 32 个字符:

substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", mt_rand(0, 51), 1).substr(md5(time()), 1);

小写版本:

substr("abcdefghijklmnopqrstuvwxyz", mt_rand(0, 25), 1).substr(md5(time()), 1);

甚至更短、更快的小写版本:

chr(mt_rand(97, 122)).substr(md5(time()), 1);

/* or */

chr(mt_rand(ord('a'), ord('z'))).substr(md5(time()), 1);


给任何试图在一秒钟内生成许多随机字符串的人的注意事项:
由于
time( ) 返回时间以秒为单位, md5( time( ) ) 在给定的第二次时间中将是相同的,因此如果在第二次时间内生成了许多随机字符串,那些可能最终可能会有一些重复。


我已经使用下面的代码进行了测试。这测试小写版本:

    $num_of_tests = 100000;

    $correct = $incorrect = 0;

    for( $i = 0; $i < $num_of_tests; $i++ )
    {
        $rand_str = substr( "abcdefghijklmnopqrstuvwxyz" ,mt_rand( 0 ,25 ) ,1 ) .substr( md5( time( ) ) ,1 );

        $first_char_of_rand_str = substr( $rand_str ,0 ,1 );

        if( ord( $first_char_of_rand_str ) < ord( 'a' ) or ord( $first_char_of_rand_str ) > ord( 'z' ) )
        {
            $incorrect++;
            echo $rand_str ,'<br>';
        }
        else
        {
            $correct++;
        }
    }

    echo 'Correct: ' ,$correct ,' . Incorrect: ' ,$incorrect ,' . Total: ' ,( $correct + $incorrect );
于 2013-09-26T02:20:55.693 回答
29

我发现了这样的东西:

$length = 10;
$randomString = substr(str_shuffle(md5(time())),0,$length);
echo $randomString;
于 2013-10-25T13:18:05.073 回答
6

如果你需要它以字母开头,你可以这样做。它很乱……但它是一条线。

$randomString = substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1) . substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);

echo $randomString;
于 2013-09-26T01:10:33.483 回答
6

我决定这个问题需要一个更好的答案。喜欢代码高尔夫!这也使用了更好的随机字节生成器。

preg_replace("/[\/=+]/", "", base64_encode(openssl_random_pseudo_bytes(8)));

显然,增加更长密码的字节数。

于 2014-09-04T08:54:38.073 回答
4

创建一个 200 字符长的十六进制字符串:

$string = bin2hex(openssl_random_pseudo_bytes(100));

maaarghk 的回答虽然更好。

于 2014-09-04T18:26:56.690 回答
3

base_convert(microtime(true), 10, 36);

于 2014-05-25T05:08:49.787 回答
3

你可以试试这个:

 function KeyGenerator($uid) {
    $tmp = '';
    for($z=0;$z<5;$z++) {
      $tmp .= chr(rand(97,122)) . rand(0,100);
    }
    $tmp .= $uid;
    return $tmp;
  }
于 2015-12-26T01:10:04.763 回答
2

我已经为你生成了这段代码。简单、简短且(相当)优雅。

这使用你提到的base64,如果长度对你不重要 - 但是它使用str_replace删除“==”。

<?php
        echo  str_ireplace("==", "", base64_encode(time()));
?>
于 2013-09-26T01:14:16.767 回答
2

我用这个功能

用法:

 echo randomString(20, TRUE, TRUE, FALSE);

  /**
   * Generate Random String
   * @param Int Length of string(50)
   * @param Bool Upper Case(True,False)
   * @param Bool Numbers(True,False)
   * @param Bool Special Chars(True,False)
   * @return String  Random String
   */
  function randomString($length, $uc, $n, $sc) {
      $rstr='';
      $source = 'abcdefghijklmnopqrstuvwxyz';
      if ($uc)
          $source .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      if ($n)
          $source .= '1234567890';
      if ($sc)
          $source .= '|@#~$%()=^*+[]{}-_';
      if ($length > 0) {
          $rstr = "";
          $length1= $length-1;
          $input=array('a','b','c','d','e','f','g','h','i','j,''k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')  
          $rand = array_rand($input, 1)
          $source = str_split($source, 1);
          for ($i = 1; $i <= $length1; $i++) {
              $num = mt_rand(1, count($source));
              $rstr1 .= $source[$num - 1];
              $rstr = "{$rand}{$rstr1}";
          }
      }
      return $rstr;
  }
于 2013-09-26T01:14:58.870 回答
1

根据上面的其他很好的例子,我使用这个来一次生成几十个唯一的字符串,而不重复它们:

$string = chr(mt_rand(97, 122))
          . substr(md5(str_shuffle(time() . rand(0, 999999))), 1);

这样,我能够在大约 5 秒内生成 1.000.000 个唯一字符串。这不是那么快,我知道,但因为我只需要少数几个,我可以接受。顺便说一句,生成 10 个字符串的时间不到 0.0001 毫秒。

于 2014-11-28T15:35:45.257 回答
1

JavaScript 解决方案:

function randomString(pIntLenght) {  
  var strChars = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz”;
  var strRandomstring = ”;

  for (var intCounterForLoop=0; intCounterForLoop < pIntLenght; intCounterForLoop++) {
      var rnum = Math.floor(Math.random() * strChars.length);
      strRandomstring += strChars.substring(rnum,rnum+1);
  }
   return strRandomstring;
}

alert(randomString(20));

参考网址:使用 JavaScript 生成随机字符串

PHP解决方案:

function getRandomString($pIntLength = 30) {
      $strAlphaNumericString     = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

      $strReturnString         = ”;

      for ($intCounter = 0; $intCounter < $pIntLength; $intCounter++) {
           $strReturnString .= $strAlphaNumericString[rand(0, strlen($strAlphaNumericString) - 1)];
      }
      return $strReturnString;
}

echo getRandomString(20);

参考网址:使用 PHP 生成随机字符串

于 2014-12-24T06:34:14.073 回答
1

此函数返回随机小写字符串:

function randomstring($len=10){
 $randstr='';
 for($iii=1; $iii<=$len; $iii++){$randstr.=chr(rand(97,122));};
 return($randstr);
};
于 2015-08-18T05:28:39.707 回答
1

我发现 base64 编码对于创建随机字符串很有用,并使用这一行:

base64_encode(openssl_random_pseudo_bytes(9));

它给了我一个 12 个位置的随机字符串,还有一个额外的好处是随机性是“加密的强”。

于 2015-12-29T10:30:36.563 回答
1

要生成由随机字符组成的字符串,可以使用此函数

public function generate_random_name_for_file($length=50){
    $key = '';
    $keys = array_merge(range(0, 9), range('a', 'z'));
    for ($i = 0; $i < $length; $i++) {
        $key .= $keys[array_rand($keys)];
    }
    return $key;
}
于 2016-02-13T12:18:49.910 回答
1

这真的取决于你的要求。

我需要字符串在测试运行之间是唯一的,但没有太多其他限制。

我还需要我的字符串以一个字符开头,这对我的目的来说已经足够了。

$mystring = "/a" . microtime(true);

示例输出:

a1511953584.0997

于 2017-11-29T11:17:29.117 回答
1

如何以糟糕的方式匹配 OP 的原始请求(为提高可读性而扩展):

// [0-9] ASCII DEC 48-57
// [A-Z] ASCII DEC 65-90
// [a-z] ASCII DEC 97-122
// Generate: [A-Za-z][0-9A-Za-z]
$r = implode("", array_merge(array_map(function($a)
                             {
                                 $a = [rand(65, 90), rand(97, 122)];
                                 return chr($a[array_rand($a)]);
                             }, array_fill(0, 1, '.')),
                             array_map(function($a)
                             {
                                 $a = [rand(48, 57), rand(65, 90), rand(97, 122)];
                                 return chr($a[array_rand($a)]);
                             }, array_fill(0, 7, '.'))));

最后一个 array_fill() 会将“7”更改为您的长度 - 1。

对于所有字母数字(并且仍然很慢)的人:

// [0-9A-Za-z]
$x = implode("", array_map(function($a)
                           {
                               $a = [rand(48, 57), rand(65, 90), rand(97, 122)];
                               return chr($a[array_rand($a)]);
                           }, array_fill(0, 8, '.')));
于 2018-06-10T06:21:09.627 回答
1

以下单行符符合您问题中的要求:值得注意的是,它以字母开头。

substr("abcdefghijklmnop",random_int(0, 16),1) . bin2hex(random_bytes(15))

如果您不在乎字符串是否以字母开头,则可以使用:

bin2hex(random_bytes(16))

请注意,这里我们使用random_bytesand random_int,它是在 PHP 7 中引入的,并使用加密随机生成器,如果您希望难以猜测唯一的字符串,这一点很重要。许多其他解决方案,包括那些涉及time(), microtime(), uniqid(), rand(), mt_rand(), str_shuffle(),array_rand()和的解决方案,shuffle()如果随机字符串用作密码、承载凭证、随机数、会话标识符、“验证码”或“确认码”,或另一个秘密值。

我还列出了在生成唯一标识符时要记住的其他事项,尤其是随机标识符。

于 2020-07-27T16:38:28.600 回答