7

I'm writing a simple script to generate all combinations of a and b of a given length (say 10). I want to be able to do this on a command line (I know this is fairly easy if I just put everything in a bash script file and execute it). However, I was wondering if it's possible to do without any extra files. Here's what I have so far:

n=10;
for i in `seq 1 1 $n`; do
    echo "for a$i in {a..b}; do ";
done;
echo -n "echo ";
for i in `seq 1 1 $n`; do
    echo -n '$'"a$i"; done;
    echo;
for i in `seq 1 1 $n`; do
    echo "done;";
done

(I formatted the code for readability, but it's actually all on one line run from a prompt)

This gives me the following output:

for a1 in {a..b}; do 
for a2 in {a..b}; do 
for a3 in {a..b}; do 
for a4 in {a..b}; do 
for a5 in {a..b}; do 
for a6 in {a..b}; do 
for a7 in {a..b}; do 
for a8 in {a..b}; do 
for a9 in {a..b}; do 
for a10 in {a..b}; do 
echo $a1$a2$a3$a4$a5$a6$a7$a8$a9$a10
done;
done;
done;
done;
done;
done;
done;
done;
done;
done;

which is just fine. If I copy that and paste it back on the command line, it works like a charm and gives me the result.

The question is how do I do this with just the initial script, without copy-pasting and without redirecting anything to files.

I've tried sticking $( ) around the script, but that gives me "No command 'for' found'", since it's not really a command but a bash builtin. I've tried putting eval somewhere before this, but I just keep getting more errors. I'm a bit stuck, so any help would be greatly appreciated.

(Btw, just to reiterate, I'm doing this more or less to just learn bash more -- that's why I don't want to redirect the output to a file and then execute that file. I know how to do that part, but I don't know how to just do it from command line)

1
  • 1
    n=10; str=; for ((i=0; i < $n; ++i)); do str+='{a..b}'; done; eval echo $str Commented Feb 16, 2011 at 14:48

2 Answers 2

23

You need to use an eval, $() gives you a string.

eval $( echo echo foo )

Another option is to stick into a subshell and pipe it to a bash:

(echo echo foo) | /bin/bash
Sign up to request clarification or add additional context in comments.

4 Comments

here's what I get: user@host:/tmp$ eval $( n=10; for i in seq 1 1 $n; do echo "for a$i in {a..b}; do "; done; echo -n "echo "; for i in seq 1 1 $n; do echo -n '$'"a$i"; done; echo; for i in seq 1 1 $n; do echo "done;"; done ) bash: syntax error: unexpected end of file
Maybe I have to escape some $ or quotes?
sweet, the pipe to /bin/bash worked. I tried it before without brackets around the script and it didn't. I learned something today. :D (I'll accept as soon as it will let me)
Do realize though that you're now using three shell processes, the first is the one executing the () | sh, the second is the one executing the code in the subshell and the last is the one executing the output of the subshell. See echo $BASHPID ; ( echo echo $BASHPID ; echo echo \$BASHPID ) | /bin/bash
2

You can do for i in $(seq $n) instead of seq 1 1 $n.

You can do for ((i=1; i<=$n; i++)) and avoid calling an external utility.

You can do this (slightly hacky with only one loop):

$ a=A; b=B; n=4; s=''; for ((i=1;i<=n;i++)); do s+="{$a..$b}"; done; eval echo "''" $s"$'\n'"

or this (highly hacky without any loops):

$ a=A; b=B; n=4; eval echo "''" $(printf "{$a..$b}%.0s" $(eval echo "{1..$n}"))"$'\n'"

Either one will get you this:

 AAAA
 AAAB
 AABA
 AABB
 ABAA
 ABAB
 ABBA
 ABBB
 BAAA
 BAAB
 BABA
 BABB
 BBAA
 BBAB
 BBBA
 BBBB

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.