
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 sichFoo
in verwandeln{F,F}{o,o}{o,o}
, was ziemlich nutzlos wäre. Aber wenn Sie\U
und hinzufügen\L
, erhalten Sie den Groß- und Kleinbuchstaben jedes Buchstabens, also{F,f}{O,o}{O,o}
.- Dann müssen Sie nur noch
eval
die 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}