14

I want to write a bash script to print all possible lower and upper case permutations of a certain word, e.g. harley:

harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY

My naive solution is to write a n-th (n is len(word)) nested for-loop for this specific word:

#!/bin/bash
for a in {h,H}; do
    for b in {a,A}; do
    ...
    done
done

However, I would have to code the script for a different word again.

Is there a better way to accomplish this?

18

A slightly better solution:

echo {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y}

For full scalability:

echo harley \
| perl -nle 'print "echo ",
                    join "",map { "{" . lc . "," .uc ."}" } split //' \
| xargs -I {} bash -c "{}"

If you absolutely must have one word per line, go with

for w in {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y};do echo $w;done

thanks to mattdm's comment

The corresponding scalable version would be:

echo harley \
| perl -nle 'print join "",map { "{" . lc . "," .uc ."}" } split //' \
| xargs -I {} bash -c 'for w in {};do echo $w;done'

For fun, try replacing "harley" with "supercalifragilisticexpialidocious" It's been 5 minutes and my computer is still crunching on this one and will probably never finish :)

  • 1
    for w in {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y}; do echo $w;done – mattdm Nov 16 '14 at 4:58
  • 4
    A still simpler one-per-line solution: printf '%s\n' {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y} – John1024 Nov 16 '14 at 7:42
  • 2
    @John1024 I encourage you to post that as an answer, it is an under-appreciated feature of bash's printf – steeldriver Nov 16 '14 at 13:12
10
eval echo $(echo "word" | sed 's/./{\U&,\L&}/g')
  • sed 's/./{&,&}/g' would turn Foo into {F,F}{o,o}{o,o}, which would be pretty useless.  But add \U and \L and you get the upper and lower case of each letter; i.e., {F,f}{O,o}{O,o}.
  • Then it’s a simple matter of using eval to tell the shell to expand the {X,x} brace sequences.
  • 1
    Nice trick :). If I could accept two answers, yours would be accepted, too! Upvote anyway – polym Nov 19 '14 at 10:25
5

EDIT 2: This answer is wrong. It doesn't produce 2^n combinations as it should.

EDIT: I don't know why, but this solution is realy fast compared to the perl solution by @Joeseph R. It runs "Supercalifragilisticexpialidocious" in less than 0.3 seconds!

Here's my crack at it:

#!/bin/bash

str=${1^^}  # convert to uppercase
len=${#str} # get length of string

for ((perm=0; perm <= len; perm++)); do
    for ((i=0; i <= len; i++)); do
        lower=${str,,}   # convert to lowercase

        # Uppercase n-th letter for permutation
        if [ $perm -gt 0 ]; then
            nth=${lower:perm-1}
            lower=$(echo ${lower:0:perm-1}${nth^})
        fi

        echo -n ${str:0:i} # print orig string from 0 to $i
        echo ${lower:i}    # print new string from $i to end
    done
done | sort -u

Running it:

$ ./permutations.sh hi
hi
hI
Hi
HI

$ ./permutations.sh harley
harley
harleY
harlEy
harLey
haRley
hArley
Harley
HarleY
HarlEy
HarLey
HaRley
HArley
HArleY
HArlEy
HArLey
HARley
HARleY
HARlEy
HARLey
HARLeY
HARLEy
HARLEY

Feel free to fork and modify it, I'm sure it can be optimized. https://gist.github.com/ryanmjacobs/4c02ad80f833dee0c307

  • 1
    The code clearly does not print all results. With harley you should have 64 results, where's harLEY, for example? – Denis Nov 17 '14 at 7:25
  • 1
    @Denis Yup you're right. Every time there should be 2^n results, where n is the number of characters of the original string. This answer is wrong. – ryanmjacobs Nov 18 '14 at 0:50
0

If you prefer to use ready tools instead of coding, you can use TextMechanic (permutation/combination generator tool) and Unit-Conversion.info

  • How would they get and use those tools, exactly? – Jeff Schaller Jan 30 at 16:54
  • This answer could be greatly improved by adding a few details such as the home pages or GitHub repositories for these projects and/or if they can be installed from a package. – Anthony Geoghegan Jan 30 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.