生成从 0.00.00_aa 到 9.99.99_zz 的单词

Generating words from 0.00.00_aa to 9.99.99_zz

我想通过 bash 脚本生成。

所需的输出应该是这样的:

0.00.0    
0.00.00
0.00.01
...
1.26.0
1.26.00
1.26.01
1.26.02
...
0.00.0_a
...
0.00.0_z
0.00.00_a
...
0.00.01_a
...
9.99.99_z
...
0.00.0_aa
...
0.00.00_aa
...
1.26.99_zz
...
9.99.99_zz

我找到这个:

printf "%03d\n" {0..999}

但是这个脚本的输出是:

000
001
002
...
997
998
999

那么,如何修改此脚本以获得我想要的输出?

连接 多个大括号扩展以构建其笛卡尔积。也就是说,要生成 00 01 ... 99 你可以写 {0..9}{0..9}。从 bash 4.0 开始你也可以写 {00..99}。这仅适用于数字。对于字母,您仍然必须写 {a..z}{a..z}.

对于 0 00 01 02 ... 99 中的单个 0,您可以 嵌套 大括号扩展,如下所示:{0,{00..99}}。对于我们使用空字符串的缺失字母也是如此:{,{a..z}}.


警告:以下命令占用大量内存。磁盘上的输出可能“仅”约 750 MB,但 运行ning bash 进程为我使用了 超过 16 GB 的内存。如果你没有足够的 memory/swap 命令可能会被杀死(如果你幸运的话)或者你的 系统冻结 ,需要你做一个 硬重启 .

要获得更好的解决方案,请参阅此答案的结尾。


现在让我们把所有东西放在一起:

printf %s\n {0..9}.{00..99}.{0,{00..99}}{,_{,{a..z}}{a..z}} > outputFile

这个大括号扩展生成 71'003'000 行,将它们打印到标准输出需要很长时间,因此我们将输出重定向到文件 outputFile。您可以通过 运行ning grep -Fxf exampleAsAFile outputFile 确认这至少会生成示例中的行。或者,运行 这个简化的命令,我们将 0..9 替换为 0..1,将 a..z 替换为 a..b,然后手动检查结果:

printf %s\n {0..1}.{0..1}{0..1}.{0,{0..1}{0..1}}{,_{,{a..b}}{a..b}}

尽管我们刚刚生成了所有必需的行,但顺序与您的示例不同。要调整顺序,您可以通过 Schwartzian transform sort 运行 结果,但这会浪费资源。相反,您可以使用多个大括号扩展,以便以正确的顺序生成所有内容:

printf %s\n \
  {0..9}.{00..99}.{0,{00..99}} \
  {0..9}.{00..99}.{0,{00..99}}_{a..z} \
  {0..9}.{00..99}.{0,{00..99}}_{a..z}{a..z} \
  > outputFile

减少内存占用

要减少内存占用,您可以将前缀拆分为 for 循环。具体在哪里拆分取决于您的偏好和系统。循环中更少的大括号意味着更多的内存但执行速度更快(只要你有足够的内存)。循环中更多的大括号意味着执行速度更慢但内存更少(只要前缀短于大括号扩展的一半;使其更长只会产生负面影响)。

# use only if order doesn't matter. 
# takes 1m30s and 24 MB of memory
for prefix in {0..9}.{00..99}; do
    printf "$prefix.%s\n" {0,{00..99}}{,_{,{a..z}}{a..z}}
done > outputFile

# takes 2m and 24 MB of memory
for prefix in {0..9}.{00..99}; do
  printf "$prefix.%s\n" {0,{00..99}} >> part1
  printf "$prefix.%s\n" {0,{00..99}}_{a..z} >> part2
  printf "$prefix.%s\n" {0,{00..99}}_{a..z}{a..z} >> part3
done
cat part{1..3} > outputFile