General
cancel
Showing results for 
Search instead for 
Did you mean: 

Help me with this shell script pls..

Karthik_sg
Frequent Advisor

Help me with this shell script pls..

The output expected out of the script is that a,b,c,....z should have all the combinations of alphabets and numbers with it For ex: first line o/p should be
1.ab
2.ac
3.ad
.
.
.
az
aba
abc
abd
.
.
.
.......till a9999999........9........9

can any 1 tel me how to do it.i have loaded the array for u in the below program.Thanks in advance.

#!/bin/sh
j=0;
for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
do
dod[$j]=$i;
echo "${dod[$j]}";
i=$i+1;
j=$j+1;
done
12 REPLIES
Glenn S. Davidson
Trusted Contributor

Re: Help me with this shell script pls..

It might help to know what you are intending to do. Just to get:

aa
ab
ac
ad
.
.
.
ax
ay
az
ba
bb
bc
bd

You are going to need multiple loops. Just incrementing the variable by 1 isn't doing anything.
Conformity Destroys a mans initiative and independence. It supresses his powerful inner drive to do his own thing.
Stuart Browne
Honored Contributor

Re: Help me with this shell script pls..

Why does it sound like you're trying to make something to brute-force a password?
One long-haired git at your service...
Hein van den Heuvel
Honored Contributor

Re: Help me with this shell script pls..

Karthik,

Do you realize how many solutions you are asking? If was ignore the special case you seem to request for spaces not at the end, there will be N to the power of N solutions where N is the number of characters to use.
So if the string just goes from a .. c then there are 9 solutions. But from a .. j gives 10 billion solutions. It goes uphill very quickly form there. Exponentially!

Clearly not a job for a shell script.
Not really a job for perl either, but for a real C program... if it is a real job to begin with and not a 'student exam question'.

The seemingly 'growing' string length can be handle by adding a 'space' in front of the a .. z sequence.

You also seem to have an odd end condition:
'a99999...9' !
not
'z99999...9' ?
nor
'999999...9' ?

Anyway...
Here is SAMPLE solution in PERL.
A REAL solution must be in a compiled language and would not 'built' the output string over an over but rather 'maintain' it while it maintains the counters.

use strict;
use warnings;
my (@current,@symbols,$max,$j);
my $count = 0;
my $total = 0;
my $i = 0;
my $very_last = 0;

for (' ', 'a'..'c', '0'..'2') {$current[$count] = 0; $symbols[$count++] = $_}
$count--;
$max = $count**$count;
while (!$very_last) {
my $text = '';
for $j (0..$count) { $text .= $symbols[$current[$j]] }
printf "%7d $text\n", $total++, $text;
for $j (0..$count) {
if ($j == $count) { $very_last++; last }
my $x = $current[$j];
if (($j && $x++ < $count) || $x++ < 3 ) {
$current[$j] = $x;
last;
} else {
$current[$j] = 1;
}
}
}
print "Lines: $total\n"


Sample results below....
Close to what is requested... all values are there... for a small subset.
( Send money and I'll get them in the right order :-)
Enjoy!
Hein.


0
1 a
2 b
3 c
4 aa
5 ba
6 ca
7 ab
8 bb
9 cb
10 ac
11 bc
12 cc
13 a0
14 b0
15 c0
16 a1
17 b1
18 c1
19 a2
20 b2
21 c2
22 aaa
:
27988 a12222
27989 b12222
27990 c12222
27991 a22222
27992 b22222
27993 c22222
Lines: 27994
Hein van den Heuvel
Honored Contributor

Re: Help me with this shell script pls..

Ooops, forgot the 'retain format flag'


use strict;
use warnings;
my (@current,@symbols,$max,$j);
my $count = 0;
my $total = 0;
my $i = 0;
my $very_last = 0;

for (' ', 'a'..'c', '0'..'2') {
$current[$count] = 0;
$symbols[$count++] = $_;
}
$count--;
while (!$very_last) {
$total++;
my $text = '';
for $j (0..$count) { $text .= $symbols[$current[$j]] }
print $text,"\n";
for $j (0..$count) {
if ($j == $count) { $very_last++; last }
my $x = $current[$j];
if (($j && $x++ < $count) || $x++ < 3 ) {
$current[$j] = $x;
last;
} else {
$current[$j] = 1;
}
}
}
print "Lines: $total\n"


Hein.

Stuart Browne
Honored Contributor

Re: Help me with this shell script pls..

Hein, it's pretty easy to do in a bash shell too.. at least with bash/ash/ksh.

The iteration can be simply done with a stacked list with a an iterator:

${STACK:$ITERATOR:1}

Can easy go for infinite depth.. but it's output could get messy after a while.

In any case, the original post still looks like it's set up to try brute-force a password..

Karthik, what is the purpose of the list supposed to be?
One long-haired git at your service...
Hein van den Heuvel
Honored Contributor

Re: Help me with this shell script pls..

>> Hein, it's pretty easy to do in a bash shell too..

Easy? I respectfully disagree.
The code perhaps, sure.
But not the execution.
Maybe I'm missing something and my math is terribly wrong wrong but here is my thinking:

Taking a .. c you can make 3*3*3 = 27 combo's right? And a few more if you add in trailing spaces, as per example below?

To stay with comprehensive numbers, let's now limit ourself to an 11 character alphabeth : a..k.
Pick 1 -> 11 options
Pick twice --> 11*11 = 121 options
Pick three ---> 11*11*11 = 1331 options
Pick 11 ----------> 11 to the power of 11 is 285,311,670,611 options
Average output is 11-ish bytes (count seperator)
So for that miniscule subset the script will generate 3 Terabyte of data. Somehow I'm thinking a shell script will have just a tad too much overhead to finish that in a reasonable time window.
Make the alphabeth 13 long and we are up to 4000 Terabyte.

Cheers,
Hein.

Changing script above to read:

>>> for (' ', 'a'..'c') {

We get:

$ perl tmp.pl

a
b
c
aa
ba
ca
ab
bb
cb
ac
bc
cc
aaa
baa
caa
aba
bba
cba
aca
bca
cca
aab
bab
cab
abb
bbb
cbb
acb
bcb
ccb
aac
bac
cac
abc
bbc
cbc
acc
bcc
ccc
Lines: 40
Stuart Browne
Honored Contributor

Re: Help me with this shell script pls..

Putting into memory is the mistake you're making. You're just after output.

A few while loops, and you're done. Completely dynamic output creation, stacking letters on to each other.

I've got one here that's about 40 lines long that (just mucking around) is brute-forcing a 32 character password. Admittadly, it's only been running for about 3 mintues thus far ;) I give it another 10 or so :P

[root@logs tmp]# ./test.sh
1: a
2: b
3: c
4: aa
5: ab
6: ac
7: ba
8: bb
9: bc
10: ca
11: cb
12: cc
13: aaa
14: aab
15: aac
16: aba
17: abb
18: abc
19: aca
20: acb
21: acc
22: baa
23: bab
24: bac
25: bba
26: bbb
27: bbc
28: bca
29: bcb
30: bcc
31: caa
32: cab
33: cac
34: cba
35: cbb
36: cbc
37: cca
38: ccb
39: ccc

The output of it limited to abc/3-chara-long.
One long-haired git at your service...
Karthik_sg
Frequent Advisor

Re: Help me with this shell script pls..

No i am not trying to get a Brute force method or sumthing.Its just that sum 1 had told we can do this via shell script or perl script .Can u guys post the code of what u tried.I had been tryin this since days.Is there any logic for this Problem-If so just tel me that i wil do the rest and post the code back to u
Stuart Browne
Honored Contributor

Re: Help me with this shell script pls..

This code can be neatened up a bit, but it works:

-=-=-=-=-=-=-=-=-=-=-=-=-=-
#!/bin/bash

STACK="abc"

MAX_DEPTH=3
DEPTH=0
TOT=0

declare -a STUMP ITERATOR

ITERATOR[$DEPTH]=0

while [ $DEPTH -lt $MAX_DEPTH ]
do
let TOT++
COUNT=0
STRING=""
while [ $COUNT -le $DEPTH ]
do
STRING="${STRING}${STACK:${ITERATOR[$COUNT]}:1}"
let COUNT++
done
printf "%7s: %s\n" $TOT "${STRING}"

COUNT=$DEPTH
LAST=0
while [ $COUNT -ge 0 ]
do
if [ ${ITERATOR[$COUNT]} -eq $((${#STACK} - 1)) ]
then
ITERATOR[$COUNT]=0
else
LAST=1
let ITERATOR[$COUNT]++
continue 2
fi
let COUNT--
done

if [ $LAST == 0 ]
then
let DEPTH++
ITERATOR[$DEPTH]=0
fi
done
-=-=-=-=-=-=-=-=-=-=-=-=-=-
One long-haired git at your service...
Hein van den Heuvel
Honored Contributor

Re: Help me with this shell script pls..

Stuart wrote> Putting into memory is the mistake you're making. You're just after output.


No and No. The per script does not put it into memory either. I was just after proving that it can not be done with reasonable resources.

>> I've got one here that's about 40 lines long that (just mucking around) is brute-forcing a 32 character password.

Why would you try that if you know there does not exist storage in the world to hold the results (5e49 bytes... a 5 with 49 zeroes behind it)?

Karthik> Its just that sum 1 had told we can do this via shell script or perl script .

NOT with the specification you provided.


>> Can u guys post the code of what u tried.

Perl script above

Just change
>> for (' ', 'a'..'c', '0'..'2') {
:
>> if (($j && $x++ < $count) || $x++ < 3 ) {

To

>>>> for (' ', 'a'..'z', '0'..'9') {
:
>>>> if (($j && $x++ < $count) || $x++ < 26 ) {

If you want to go to 9999...9 the change last to:
>>>> if ($x++ < $count) {

Bash script was already posted below your reply above this one.

> I had been tryin this since days.

Ouch!

> Is there any logic for this Problem-

I just use a simple counting technique for a radix-N number.
You know 1 + 1 = 2...
9 + 1 = 0 and increment the next cell.
'a' + 1 = 'b'
'z' + 1 = ' ' and increment the next cell.

Instead of outputting each cell directly, i look up the 'picture' in a table.
One could also count in pictures of course.


On an HP BL860c, with just 7 output chars, the perl script generates the 960801 words in 9.3 seconds.
I killed the shell script after 11:31.6 minutes ( user 7:07.3, sys 1:50.2) just before it was done :-(.
I should have trusted my ball park duration guestimate of 10 minutes better, allowing for a little more.

$ wc -lc *.tmp
931315 7290395 bash.tmp
960801 8647214 perl.tmp

Hope this helps some,
Hein van den Heuvel (at gmail dot com)
HvdH Performance Consulting


Stuart Browne
Honored Contributor

Re: Help me with this shell script pls..

The perl script there is refusing to start with the numbered values.. was that intentional?
One long-haired git at your service...
Hein van den Heuvel
Honored Contributor

Re: Help me with this shell script pls..

Surprised at the runtime difference?
I wasn't. Mind you, I tried under HPUX un Itanium, not Linux where bash might be more optimized.

>> The perl script there is refusing to start with the numbered values.. was that intentional?

Yes,
following the 'suggestion' in the original question:
".......till a9999999........9........9 "

In an earlier reply I questioned whether that leading 'a' was intentional (symbol or password requirement) or just careless.

It was implemented with the line
>> if (($j && $x++ < $count) || $x++ < 3 ) {
So is $j, the column counter is not zero = true then go through all sample characters. If it is not true then use a different stopper, here hardcoded at 3 = 'c'.
To generate all, simplify that line to:
>> if ($x++ < $count) {

Didn't i write that already above?

I maintain that if this was to be part of a serious application, then a 'real' compiled langues is in order, not perl and certainly not a shell. The generated data should not be stored/listed, but consumed there and then.


If it was a brute-force password cracker, then uppercase would probably need to be part of the character set:
>> for (' ', 'A'..'Z', 'a'..'f', '0'..'9') {

And you could restrict yourself to say 12 chars giving 'only' (26+26+10)**12 words.

Cheers,
Hein.