如何使用Erlang生成随机字母数字字符串?

时间:2012-10-08 20:14:48

标签: string utf-8 erlang

我正在尝试使用Erlang生成随机字母数字ID。 我天真地尝试crypto:strong_rand_bytes(Bytes)生成一个随机二进制文件然后使用那个用<<"my_unique_random_id">>创建的二进制文件 - 这不起作用,因为随机位不一定是有效的UTF-8字符串,对吧? / p>

好吧,我在erlang文档和其他地方寻找其他选项,但我没有找到任何东西。有人能指出我的解决方案吗?

6 个答案:

答案 0 :(得分:13)

这可能取决于您需要的随机性。 Erlang的crypto模块产生比random模块更强的随机数据(另请参阅[erlang-questions] Yaws security alert - Yaws 1.93this question)。如果您想使用strong_rand_bytes生成ID,可能只需获取它的base64就可以了:

> base64:encode(crypto:strong_rand_bytes(Bytes)).

如果需要,您可以将其转换为列表。

答案 1 :(得分:12)

根据Generating random strings in Erlang,只需要几行Erlang就能从一组特定的字符集中生成一个指定长度的字符串。

get_random_string(Length, AllowedChars) ->
    lists:foldl(fun(_, Acc) ->
                        [lists:nth(random:uniform(length(AllowedChars)),
                                   AllowedChars)]
                            ++ Acc
                end, [], lists:seq(1, Length)).

博客文章对代码进行了逐行说明。查看几条优化提示的评论。

答案 2 :(得分:3)

我准备了小模块做到这一点 它还使用crypto:rand_uniform/2但不是过时的random:uniform

module(cloud_rnd).

-export([rnd_chars/1, rnd_numbers/1, rnd_chars_numbers/1]).

rnd_chars(L)         -> get_rnd(L, chars).
rnd_numbers(L)       -> get_rnd(L, numbers).
rnd_chars_numbers(L) -> get_rnd(L, chars_numbers).

get_rnd(L, chars)         -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz");
get_rnd(L, numbers)       -> gen_rnd(L, "1234567890");
get_rnd(L, chars_numbers) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz1234567890").

gen_rnd(Length, AllowedChars) ->
  MaxLength = length(AllowedChars),
  lists:foldl(
    fun(_, Acc) -> [lists:nth(crypto:rand_uniform(1, MaxLength), AllowedChars)] ++ Acc end,
    [], lists:seq(1, Length)
  ).

答案 3 :(得分:2)

对各种反应的问题&#34;我需要随机字符串&#34;问题(用任何语言)几乎每个解决方案都使用有缺陷的规范,即字符串长度。问题本身很少揭示为什么需要随机字符串,但我会大胆地假设它们将被用作需要唯一的标识符。

有两种主要方法可以获得严格的唯一字符串:确定性(非随机)和存储/比较(繁重)。该怎么办?放弃鬼魂。改为使用概率唯一性。也就是说,接受一些(但是很小的)风险,你的字符串不会是唯一的。这是理解碰撞概率和熵有用的地方。

因此,我需要重复我的大胆假设,因为您需要一些具有较小重复风险的标识符。作为一个具体的例子,让我们说你需要500万个ID,其重复风险不到1万亿。那么你需要多长的弦?那么,这个问题是不明确的,因为它取决于使用的字符。但更重要的是,它被误导了。你需要的是字符串熵的规范,而不是它们的长度。

这是EntropyString可以提供帮助的地方。

Bits = entropy_string:bits(5.0e6, 1.0e12).
83.37013046707142
entropy_string:random_string(Bits).
<<"QDrjGQFGgGjJ4t9r2">>

还有其他预定义的字符集,您也可以指定自己的字符(虽然出于效率原因,仅支持2个字符的幂集)。最重要的是,在指定数量的字符串中重复的风险是明确的。不再猜测字符串长度。

答案 4 :(得分:1)

randchar(N) ->
   randchar(N, []).

randchar(0, Acc) ->
   Acc;
randchar(N, Acc) ->
   randchar(N - 1, [random:uniform(26) + 96 | Acc]).

答案 5 :(得分:0)

您可以从此处使用函数uef_bin:random_latin_binary/2https://github.com/DOBRO/uef-lib#uef_binrandom_latin_binary2

Bin = uef_bin:random_latin_binary(Length, any)

然后,如果您需要string()类型:

String = erlang:binary_to_list(Bin)