Я пытаюсь вывести все возможные комбинации между {a..z} и {0..9}; этот вывод без использования таких инструментов, как crunch:

$ head wordlist.txt

a
b
c
1
2
3
aa
ab
ac
a1

$ tail wordlist.txt

333332c
3333321
3333322
3333323
333333a
333333b
333333c
3333331
3333332
3333333

Можем ли мы сделать с регулярным выражением? Я пробовал сочетания таких вещей, как:

for i in $(<magic here>); do
  echo "$i"
done

Но это ни к чему не привело ...

2 ответа2

1

Проблема в том, что это очень быстро получается: все перестановки из 6 символов по 36 (строчные + цифры): 36 ** 6 = 2176782336, что составляет 2176 миллионов. Умножьте на размер (6) и вам понадобится 12 гигабайт. Таким образом, вы не можете создать весь список. Если вы не можете использовать "генераторы", как у вас в Python (которые генерируют значения цикла по мере необходимости), вам нужно сделать что-то вроде:

for t1 in $chars; do 
    for t2 in $chars; do 
        for t3 in $chars; do 
            for t4 in $chars; do 
                for t5 in $chars; do
                    echo $t1$t2$t3$t4$t5
                done
            done
        done
    done
done

Если вам нужны более короткие строки:

#! /bin/bash

chars=('' a b c)

for t1 in "${chars[@]}"; do 
    for t2 in "${chars[@]}"; do 
        for t3 in "${chars[@]}"; do
            echo $t1$t2$t3
        done
    done
done

Согласно моему системному монитору, код не значительно увеличивает объем памяти, используемой процессом bash (около 2 МБ, в то время как он производит 29,5 МБ выходных данных в соответствии с pv -b). Для сравнения это эквивалентный код (с несколько более короткими списками):

for t in {a..t}{a..t}{a..t}{a..t}{a..t} ; do 
    echo $t
done

Требуется 600 МБ оперативной памяти для запуска.

Выбирать мудро :)

0

В зависимости от того, насколько точным вам нужно это сделать, и сносными накладными расходами, вы можете уйти с чем-то вроде

echo {\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}

Где бы вы повторили {\, {A ..Бит Z}, {a..z}, {0..9}} для каждого набора - т. Е. Если вы хотите, чтобы каждое слово было не более 10 символов, вы бы повторили его 10 раз.

В этом есть недостаток кода (поскольку он не распознает "нет символа" в начале, я использовал «» в качестве заполнителя. Это создаст дубликаты - то есть "99" и "99". Вы можете избавиться от них, протолкнув его через фильтр sort | uniq (и, возможно, также используя tr), но в зависимости от вашего приложения и размера конечного результата, вы можете столкнуться со временем, которое потребуется для создания список.

Чтобы создать список, который будет выводить все перестановки без дубликатов, но в порядке, отличном от вашего исходного ввода, вы можете использовать

for each in {\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}} ; do  echo $each; done | tr -d " " | sort -u

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .