Java 生成词表

Java generate wordlist

我在这个主题上卡了大约 3 天,我想不出合适的算法。 那么你们能帮帮我吗?

我想用给定的字符集最小最大长度[=生成单词表16=]

给定 charset:abcdef min:2 max:5

结果:

aa
ab
ac
...
ffffd
ffffe
fffff

喜欢linux命令行crunch

但是有些事情,我需要在 for 循环中实现它,这与循环次数无关但很重要不调用任何用户创建的函数*。

喜欢:

for (...) {

   // Password is ready!
   pass = ...;

}

不喜欢:


pass = get_pass(...);

谢谢。

一种方法是使用库数组,它从给定的正则表达式创建字符串,如 Generex。使用 Generex,您的任务非常简单:

import com.mifmif.common.regex.Generex;

public class Example {

    public static void main(String[] args) {
        Generex gen = new Generex("[abcdef]{2,5}");
        gen.getAllMatchedStrings().forEach(System.out::println);
    }
} 

输出:

aa
aaa
aaaa
aaaaa
aaaab
aaaac
aaaad
aaaae
aaaaf
...
...
ffffa
ffffb
ffffc
ffffd
ffffe
fffff

查看此 post 了解其他库,例如 generex using-regex-to-generate-strings-rather-than-match-them

我很确定这不是最好的解决方案,但它确实有效。

public static void main(String[] args) {
    List<Character> charset = new ArrayList<>();
    charset.add('a');
    charset.add('b');
    charset.add('c');
    charset.add('d');
    charset.add('e');
    int min = 2;
    int max = 5;

    List<Integer> word = new ArrayList<>();
    for (int len = min; len <= max; len++) {
        word.clear();
        for (int i = 0; i < len; i++) {
            word.add(0);
        }
        while (word.get(0) < charset.size()) {
            System.out.println(word.stream()
                    .map(e -> charset.get(e).toString())
                    .collect(Collectors.joining()));
            word.set(len - 1, word.get(len - 1) + 1);
            for (int i = len - 1; i > 0; i--) {
                if (word.get(i).equals(charset.size())) {
                    word.set(i - 1, word.get(i - 1) + 1);
                    word.set(i, 0);
                } else {
                    break;
                }
            }
        }
    }
}

另一种方法是将您的字符集解释为数字系统的数字,并将您想要的输出解释为所有 n 位数字。例如,在十进制系统中,我们有数字 0 到 9,所有两位数字(前导零)都是数字

00 - 99

三位数

000 - 999 

等等。然而,在八进制系统中,您的数字将从

00 - 77 或来自

000 - 777

和二进制

00 - 11

000 - 111

如果我们现在将字符集中的字母替换为数字,即 a 替换为 0b 替换为 1c 替换为 2 ...

输出中的

aaa000 相同,fff555 相同。这意味着任务是在基数六数字系统(字符集长度)中创建所有两位数、三位数、……、五位数字,并将数字转换回给定字符集中的字母。这种算法的起点可能是这样的:

public static void main(String[] args) {
    String str = "abcdef";

    //create a map which looks like {0=a, 1=b, 2=c, 3=d, 4=e, 5=f}
    Map<Character,Character> map = new HashMap<>();
    for(int i = 0; i <str.length(); i ++){
        map.put((char)(i+'0'), str.charAt(i));
    } 

    //convert numbers to string using //Integer.toString(int i, int radix)
    //use String#format & String#replace to have a string representation with leading zeros
    for(int n = 2; n <= 5; n++){
        int maxValue = (int)Math.pow(str.length(), n);
        for(int i = 0; i < maxValue; i++){
            String temp = String.format("%"+n+"s", Integer.toString(i, str.length())).replace(' ', '0');
            for(char c: map.keySet()){
                temp = temp.replace(c, map.get(c));
            }                
            System.out.println(temp);
        }
    }
}