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

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

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

harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY

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

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

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

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

решение1

Чуть лучшее решение:

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" на"суперкалифрагилистическийэкспиалидоциозный"Прошло уже 5 минут, а мой компьютер все еще работает над этим и, вероятно, никогда не закончит :)

решение2

оценка эхо $(echo "слово" | sed 's/./{\U&,\L&}/g')
  • sed 's/./{&,&}/g'превратится Fooв {F,F}{o,o}{o,o}, что будет довольно бесполезно. Но добавьте \Uи \Lи вы получите верхний и нижний регистр каждой буквы; т. е {F,f}{O,o}{O,o}. .
  • Затем достаточно просто указать evalоболочке, что нужно развернуть {Икс,Икс} фигурные скобки.

решение3

ПРАВКА 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

решение4

Я написал несколько простых функций на основе лучшего ответа, которые будут выводить данные в желаемом формате.

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
}

Использование/пример:

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

Связанный контент