Bash: membuat daftar kata


0

Saya mencoba menampilkan setiap kemungkinan kombinasi antara {a..z} dan {0..9}; output ini tanpa menggunakan alat suka 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

Bisakah kita lakukan dengan regex? Saya mencoba kombinasi hal-hal seperti:

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

Tapi itu tidak membuat saya ...

Jawaban:


1

Masalahnya adalah ini menjadi sangat besar dengan cepat: semua permutasi 6 karakter di sepanjang 36 (huruf kecil + digit): 36 ** 6 = 2176782336 yaitu 2176 juta. Kalikan dengan ukuran (6) dan Anda membutuhkan 12 Gigabytes. Jadi, Anda tidak dapat benar-benar menghasilkan seluruh daftar. Jika Anda tidak dapat menggunakan "generator" seperti yang Anda miliki di Python (yang menghasilkan nilai loop sesuai kebutuhan Anda), Anda perlu melakukan sesuatu seperti:

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

Jika Anda membutuhkan string yang lebih pendek:

#! /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

Menurut monitor sistem saya, kode tidak secara signifikan meningkatkan memori yang digunakan oleh proses bash (sekitar 2MB selama ini sementara menghasilkan output 29,5MB menurut pv -b ). Sebagai perbandingan, kode yang setara ini (dengan daftar yang sedikit lebih pendek):

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

Membutuhkan 600MB RAM untuk dijalankan.

Pilihlah dengan bijak :)


xenoid - apakah Anda menurunkan saya? Juga, jawaban Anda tidak membahas kasus "a", "aa" dll
davidgo

Tidak, saya tidak melakukan downvote apa pun ... Memperbarui solusi untuk menampilkan string yang lebih pendek ...
xenoid

0

Bergantung pada seberapa tepat Anda perlu melakukannya, dan overhead yang bisa ditoleransi, Anda mungkin bisa lolos dengan sesuatu seperti

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

Di mana Anda akan mengulangi {\, ​​{A..Z}, {a..z}, {0..9}} bit untuk setiap set - yaitu jika Anda ingin setiap kata maksimum 10 karakter, Anda akan mengulanginya 10 kali.

Ada kekurangan dalam kode itu (karena tidak mengenali "tidak ada karakter" di awal, saya telah menggunakan "" sebagai pengganti. Ini akan membuat duplikat - yaitu "99" dan "99". Anda dapat singkirkan ini dengan mendorongnya melalui semacam | uniq filter (dan mungkin menggunakan tr juga), tetapi tergantung pada aplikasi Anda dan ukuran hasil akhir, Anda mungkin kesulitan dengan waktu yang diperlukan untuk membuat daftar.

Untuk membuat daftar yang akan menampilkan semua permutasi tanpa duplikat, tetapi dalam urutan berbeda dengan input asli Anda, Anda dapat menggunakan

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.