Uzyskaj wszystkie możliwe kombinacje słowa małymi / dużymi literami

14

Chcę napisać skrypt bash, aby wydrukować wszystkie możliwe kombinacje małych i wielkich liter danego słowa, np. Harley:

harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY

Moim naiwnym rozwiązaniem jest napisanie n-tej (n to len (słowo)) zagnieżdżonej pętli for dla tego konkretnego słowa:

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

Jednak musiałbym ponownie zakodować skrypt dla innego słowa.

Czy istnieje lepszy sposób na osiągnięcie tego?

polim
źródło

Odpowiedzi:

18

Nieco lepsze rozwiązanie:

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

Aby uzyskać pełną skalowalność:

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

Jeśli absolutnie musisz mieć jedno słowo w wierszu, idź z

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

dzięki komentarzowi mattdm

Odpowiednia skalowalna wersja to:

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

Dla zabawy spróbuj zastąpić słowo „harley” słowem „supercalifragilisticexpialidocious” Minęło 5 minut i mój komputer wciąż się załamuje i prawdopodobnie nigdy się nie skończy :)

Joseph R.
źródło
1
dla w za {h, H} {a, A} {r, R} {l, L} {e, E} {y, Y}; zrób echo $ w; gotowe
mattdm
4
Jeszcze prostsze rozwiązanie jeden na linię:printf '%s\n' {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y}
John1024,
2
@ John1024 Zachęcam do opublikowania tego w odpowiedzi, jest to niedoceniana funkcja bash'sprintf
steeldriver
10
eval echo $ (echo „ słowo ” | sed 's /./ {\ U &, \ L &} / g')
  • sed 's/./{&,&}/g'zamieniłoby się Foow {F,F}{o,o}{o,o}, co byłoby całkiem bezużyteczne. Ale dodaj \Ui \Lotrzymasz wielką i małą literę każdej litery; tj {F,f}{O,o}{O,o}.
  • Następnie jest to prosta sprawa, evalaby powiedzieć powłoce, aby rozszerzyła sekwencje nawiasów { X , x }.
Scott
źródło
1
Niezła sztuczka :). Gdybym mógł zaakceptować dwie odpowiedzi, twoje również zostałyby zaakceptowane! W każdym razie
pozytywnie oceniaj
5

EDYCJA 2: Ta odpowiedź jest błędna. Nie tworzy 2 ^ n kombinacji tak jak powinno.

EDYCJA: Nie wiem dlaczego, ale to rozwiązanie jest naprawdę szybkie w porównaniu z rozwiązaniem Perla autorstwa @Joesepha R. Uruchamia „Supercalifragilisticexpialidocious” w mniej niż 0,3 sekundy!

Oto mój crack:

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

Uruchamianie:

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

Możesz go rozwidlać i modyfikować, jestem pewien, że można go zoptymalizować. https://gist.github.com/ryanmjacobs/4c02ad80f833dee0c307

ryanmjacobs
źródło
1
Kod wyraźnie nie drukuje wszystkich wyników. Z harleywas powinien mieć 64 wyników, gdzie jest harLEY, na przykład?
Denis,
1
@Denis Tak masz rację. Za każdym razem powinny być 2 ^ n wyników, gdzie n jest liczbą znaków oryginalnego łańcucha. Ta odpowiedź jest zła.
ryanmjacobs
0

Jeśli wolisz używać gotowych narzędzi zamiast kodowania, możesz użyć TextMechanic (narzędzie do generowania permutacji / kombinacji) i Unit-Conversion.info

Pomieszane
źródło
Jak dokładnie uzyskaliby i używali tych narzędzi?
Jeff Schaller
Ta odpowiedź może zostać znacznie ulepszona poprzez dodanie kilku szczegółów, takich jak strony główne lub repozytoria GitHub dla tych projektów i / lub czy można je zainstalować z pakietu.
Anthony Geoghegan