Получить все возможные комбинации слова в нижнем / верхнем регистре

14

Я хочу написать скрипт bash для печати всех возможных подстановок в нижнем и верхнем регистре определенного слова, например, harley:

harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY

Мое наивное решение состоит в том, чтобы написать n-й (n is len (word)) вложенный цикл for для этого конкретного слова:

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

Однако мне пришлось бы снова написать код для другого слова.

Есть ли лучший способ сделать это?

Polym
источник

Ответы:

18

Немного лучшее решение:

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

Для полной масштабируемости:

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

Если вам абсолютно необходимо иметь одно слово в строке, перейдите с

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

благодаря комментарию mattdm

Соответствующая масштабируемая версия будет:

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

Ради интереса попробуйте заменить "harley" на "supercalifragilisticexpialidocious". Прошло 5 минут, и мой компьютер все еще ломается и, вероятно, никогда не завершит работу :)

Джозеф Р.
источник
1
для w в {h, H} {a, A} {r, R} {l, L} {e, E} {y, Y}; do echo $ w; done
mattdm
4
Еще более простое решение для одной строки:printf '%s\n' {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y}
John1024
2
@ John1024 Я рекомендую вам опубликовать это как ответ, это недооцениваемая особенность bash'sprintf
steeldriver
10
eval echo $ (echo " word " | sed 's /./ {\ U &, \ L &} / g')
  • sed 's/./{&,&}/g'превратится Fooв {F,F}{o,o}{o,o}, что было бы довольно бесполезно. Но добавьте \Uи, \Lи вы получите верхний и нижний регистр каждой буквы; то есть {F,f}{O,o}{O,o}.
  • Тогда достаточно просто evalсказать оболочке, чтобы она расширила последовательности фигурных скобок { X , x }.
Скотт
источник
1
Хороший трюк :). Если бы я мог принять два ответа, ваш тоже был бы принят! Upvote в любом случае
Polym
5

РЕДАКТИРОВАТЬ 2: Этот ответ неверен. Он не производит 2 ^ n комбинаций, как следует.

РЕДАКТИРОВАТЬ: я не знаю почему, но это решение действительно быстро по сравнению с решением Perl @Joeseph R. Он запускает "Supercalifragilisticexpialidocious" менее чем за 0,3 секунды!

Вот моя трещина в этом:

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

Запуск это:

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

Не стесняйтесь раскошелиться и изменить его, я уверен, что он может быть оптимизирован. https://gist.github.com/ryanmjacobs/4c02ad80f833dee0c307

ryanmjacobs
источник
1
Код явно не печатает все результаты. С harleyвами должно быть 64 результата, где harLEY, например?
Денис
1
@ Денис Да, ты прав. Каждый раз должно быть 2 ^ n результатов, где n - количество символов исходной строки. Этот ответ неверен.
ryanmjacobs
0

Если вы предпочитаете использовать готовые инструменты вместо кодирования, вы можете использовать TextMechanic (инструмент перестановки / генератор комбинаций) и Unit-Conversion.info

Перепутал
источник
Как они получат и будут использовать эти инструменты?
Джефф Шаллер
Этот ответ может быть значительно улучшен путем добавления нескольких деталей, таких как домашние страницы или репозитории GitHub для этих проектов, и / или если они могут быть установлены из пакета.
Энтони