生成笛卡尔积

时间:2016-06-08 14:02:59

标签: string bash sh

我正在尝试生成一些像

这样的字符串
AAAA0000
AAAA0001
...
..
...
ZZZZ9999

我可以用以下逻辑&它会起作用

   for A in {A..Z}
    do
        for B in {A..Z}
            do
                for C in {A..Z}
                    do
                    for D in {A..Z}
                        do
                        for E in {0..9}
                            do
                            for F in {0..9}
                                do
                                for G in {0..9}
                                    do
                                        for H in {0..9}
                                        do
                                            echo $A$B$C$D$E$F$G$H

                                        done
                                    done
                                done
                            done
                        done
                    done
                done
            done
        done
    done

这是令人筋疲力尽的做法(尽管它解决了这个问题)

任何人都可以通过某种有效的方式帮助

2 个答案:

答案 0 :(得分:6)

您可以将多个括号扩展组合为:{A..Z}{A..Z}...。但笛卡儿积分超过40亿(26 * 26 * 26 * 26 * 10 * 10 * 10 * 10),将存储在内存中(如果不是更多,则约为38 GB)。

但是,您可以使用Perl或类似方法生成此列表:

perl -le 'print for "AAAA0000" .. "ZZZZ9999"' > output.txt

预计需要一些时间
这将生成一个大小约为38 GB的文件:

26 * 26 * 26 * 26 * 10 * 10 * 10 * 10 * (8 + 1) = 41,127,840,000 bytes
^    ^    ^    ^    ^    ^    ^    ^     ^   ^
A-Z  A-Z  A-Z  A-Z  0-9  0-9  0-9  0-9   |   new line
                                         8 bytes wide AAAA0000, AAAA0001, ...

41127840000 / 1024 / 1024 / 1024 = 38.30 GB
^             ^      ^      ^
Bytes         KB     MB     GB

答案 1 :(得分:3)

试试这个:

printf "%s\n" {A..Z}{A..Z}{A..Z}{A..Z}{0..9}{0..9}{0..9}{0..9}

...

嘿,当然,这可能会消耗一些记忆!

这个较小的表单在我的电脑上运行:

printf "%s\n" {A..F}{A..F}{A..F}{A..F}{0..9}{0..9}{0..9}{0..9} | wc 
12960000 12960000 116640000

当然不是编程语言,但你可以:

recurs () { 
    local level=$1 upper=$2;
    shift 2;
    ((level)) && { 
        for i in $@ ;do
            recurs $[level-1] $upper$i $@;
        done
    } || { 
        for i in $@ ;do
            echo $upper$i;
        done
    }
}

这将使递归工作:

recurs 3 '' a b c d e f | tee >(sed -ne '1p;$p') >(wc) >/dev/null ;sleep .2
aaaa
   1296    1296    6480
ffff

第二个参数是左侧部分字符串,所以做了类似问题的事情:

while read lhs ;do
    recurs 3 $lhs {0..4}
  done < <(
    recurs 3 '' {A..F}
) | tee >(sed -ne '1p;$p') >(wc) >/dev/null ;sleep .2
AAAA0000
 810000  810000 7290000
FFFF4444

而且,如果你真的想看看bash有多快:

time while read lhs ;do
    recurs 3 $lhs {0..9}
  done < <(
    recurs 3 '' {A..Z}
) | tee >(sed -ne '1p;$p') >(wc) >/dev/null ;sleep .2