Holen Sie sich alle möglichen Kombinationen eines Wortes in Klein-/Großbuchstaben

Holen Sie sich alle möglichen Kombinationen eines Wortes in Klein-/Großbuchstaben

Ich möchte ein Bash-Skript schreiben, um alle möglichen Permutationen eines bestimmten Wortes in Klein- und Großbuchstaben auszudrucken, z. B. „Harley“:

harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY

Meine naive Lösung besteht darin, eine n-te (n ist Länge(Wort)) verschachtelte For-Schleife für dieses spezielle Wort zu schreiben:

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

Allerdings müsste ich das Skript für ein anderes Wort erneut codieren.

Gibt es eine bessere Möglichkeit, dies zu erreichen?

Antwort1

Eine etwas bessere Lösung:

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

Für vollständige Skalierbarkeit:

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

Wenn Sie unbedingt ein Wort pro Zeile benötigen, wählen Sie

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

Dank anKommentar von mattdm

Die entsprechende skalierbare Version wäre:

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

Ersetzen Sie zum Spaß "harley" durch"Superkalifragilistischexpiallegetisch"Es sind schon 5 Minuten vergangen und mein Computer arbeitet immer noch daran und wird wahrscheinlich nie fertig :)

Antwort2

eval echo $(echo "Wort" | sed 's/./{\U&,\L&}/g')
  • sed 's/./{&,&}/g'würde sich Fooin verwandeln {F,F}{o,o}{o,o}, was ziemlich nutzlos wäre. Aber wenn Sie \Uund hinzufügen \L, erhalten Sie den Groß- und Kleinbuchstaben jedes Buchstabens, also {F,f}{O,o}{O,o}.
  • Dann müssen Sie nur noch evaldie Shell anweisen, das { zu erweitern.X,X} Klammerfolgen.

Antwort3

BEARBEITEN 2:Diese Antwort ist falsch. Sie erzeugt nicht wie vorgesehen 2^n-Kombinationen.

BEARBEITEN:Ich weiß nicht warum, aber diese Lösung istwirklichschnell im Vergleich zur Perl-Lösung von @Joeseph R. Es führt „Supercalifragilisticexpialidocious“ in weniger als 0,3 Sekunden aus!

Hier ist mein Versuch:

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

Ausführen:

$ ./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

Fühlen Sie sich frei, es zu verzweigen und zu modifizieren, ich bin sicher, es kann optimiert werden.https://gist.github.com/ryanmjacobs/4c02ad80f833dee0c307

Antwort4

Ich habe basierend auf der besten Antwort einige einfache Funktionen geschrieben, die die Ausgabe im gewünschten Format ermöglichen.

to_lower () 
{ 
    tr '[[:upper:]]' '[[:lower:]]' <<< $@
}
to_upper () 
{ 
    tr '[[:lower:]]' '[[:upper:]]' <<< $@
}
generate_permutations () 
{ 
    local perm="$@";
    perl -e '@foo = split(//, $ARGV[0]);foreach my $c (@foo){print "$c $c\n";}' ${perm} | while read l u; do
        echo "{$(to_lower ${l}),$(to_upper $u)}";
    done | tr -d '\n';
    echo
}

Anwendung/Beispiel:

$ generate_permutations foobar
{f,F}{o,O}{o,O}{b,B}{a,A}{r,R}

verwandte Informationen