我对此感到非常惊讶: 我正在构建一个简单的密码生成器,它使用用户创建的模式。该模式包含字母 a-f,代表 6 个字符组:
因此,如果用户输入 ababcd,他/她会得到类似
abce1!
的内容
模式 Abababababaccd 会生成类似 Robuxejiqu23#
的内容。
由于 Abababababccd 看起来很难读,我想提供通过重复缩写的可能性:
Abababababaccd 可以写成 Ab(ab){5}ccd
甚至 Ab(ab){5}c{2}d
(这可能很愚蠢,但为了完整性)。
如果想要使用 a 组或 b 组中的角色,则 [ab] 就会发挥作用。
我“构建”了一个合适的正则表达式,它捕获以下组合中的重复:
a{3}
这样的单个字符重复会变成aaa
(ab){2}
会变成abab
[ab]{2}
变为 ab
或 aa
或 ba
等(a[bc]d){n}
我到目前为止构建的正则表达式找到了上述所有情况:
/(?:(\[[abcdef]+\])|\(([\[\]abcdef]+)\)|([abcdef]))\{(\d+)\}/i
我的工作 Ruby 代码看起来像这样,但它想找到一个更优雅的解决方案:
# class
REPETITION = /(?:(\[[abcdef]+\])|\(([\[\]abcdef]+)\)|([abcdef]))\{(\d+)\}/i
GROUPS = /\[([abcdefxyz]+)\]/i;
# method generate
pattern = params[:pattern]
group = {
'A' => params[:group_a].upcase,
'a' => params[:group_a],
'B' => params[:group_b].upcase,
'b' => params[:group_b],
'C' => params[:group_c].upcase,
'c' => params[:group_c],
'D' => params[:group_d].upcase,
'd' => params[:group_d],
'E' => params[:group_e].upcase,
'e' => params[:group_e],
'F' => params[:group_f].upcase,
'f' => params[:group_f]
}
# Evaluate repetitions: ...{n}
if pattern =~ REPETITION
pattern.gsub!(REPETITION) do
match = $1 != nil ? $1 : $2 != nil ? $2 : $3
count=$4.to_i
expanded=""
count.times do
expanded+=match
end
expanded
end
end
# Evaluate character groups [...]
if pattern =~ GROUPS
pattern.gsub!(GROUPS) do
$1[rand($1.length)]
end
end
# Evaluate the final pattern (repetitions and []-groups processed)
password=""
pattern.each_char do |c|
password+=group[c][rand(group[c].length)]
end
@password=password;
我的想法是找到所有出现的情况,并用扩展的重复替换重复,以便
Ab(ab){5}ccd
变成 Ababababababccd
,然后我进行处理。
我的假设是
.gsub
单独处理每个事件,并且我可以用合适的模式和计数替换每个匹配。如果 gsub 尝试一次替换所有这些,那将是错误的方法。
对我来说, (?:a|b|c){count} 中的哪个组匹配并不重要,但匹配项应返回为 $1,计数应返回为 $2。
上述正则表达式导致匹配 $1、$2、$3 和 $4。 4 美元始终是我的重复次数。但接下来我必须找出哪个 $1 .. $3 不是
nil
并用它来扩展。我可以选择“便宜”的案例,然后if通过案例,但我想要一个优雅的解决方案。
在 regex101 中,我让它可以与
(?|
一起使用,但 Ruby 不理解。
我希望我清楚我想要什么!?
在 Typescript 和 C# 中我让它可以工作,现在我希望它能在 Ruby 中工作......:-)
我已经编辑了这个问题,以便我当前的(不优雅的)代码可供任何人使用。如果有人有好的建议,请随时发表评论或回答。