
Quero escrever um script bash para imprimir todas as possíveis permutações em maiúsculas e minúsculas de uma determinada palavra, por exemplo, harley:
harley
harleY
harlEy
harLey
...
HARLey
HARLEy
HARLEY
Minha solução ingênua é escrever um n-ésimo (n é len(word)) loop for aninhado para esta palavra específica:
#!/bin/bash
for a in {h,H}; do
for b in {a,A}; do
...
done
done
No entanto, eu teria que codificar o script para uma palavra diferente novamente.
Existe uma maneira melhor de fazer isso?
Responder1
Uma solução um pouco melhor:
echo {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y}
Para escalabilidade total:
echo harley \
| perl -nle 'print "echo ",
join "",map { "{" . lc . "," .uc ."}" } split //' \
| xargs -I {} bash -c "{}"
Se você realmente precisa de uma palavra por linha, escolha
for w in {h,H}{a,A}{r,R}{l,L}{e,E}{y,Y};do echo $w;done
graças acomentário de mattdm
A versão escalável correspondente seria:
echo harley \
| perl -nle 'print join "",map { "{" . lc . "," .uc ."}" } split //' \
| xargs -I {} bash -c 'for w in {};do echo $w;done'
Por diversão, tente substituir "harley" por"supercalifragilisticexpialidocious"Já se passaram 5 minutos e meu computador ainda está processando este e provavelmente nunca terminará :)
Responder2
avaliação echo $(eco "palavra" | sed 's/./{\U&,\L&}/g')
sed 's/./{&,&}/g'
se transformariaFoo
em{F,F}{o,o}{o,o}
, o que seria bastante inútil. Mas adicione\U
e\L
e você obterá as letras maiúsculas e minúsculas de cada letra; ou seja,{F,f}{O,o}{O,o}
.- Então é uma simples questão de usar
eval
para dizer ao shell para expandir o {X,x} sequências de chaves.
Responder3
EDITAR 2:Esta resposta está errada. Não produz 2 ^ n combinações como deveria.
EDITAR:Não sei porquê, mas esta solução érealmenterápido em comparação com a solução perl de @Joeseph R. Ele executa "Supercalifragilisticexpialidocious" em menos de 0,3 segundos!
Aqui está minha chance:
#!/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
Executando:
$ ./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
Sinta-se à vontade para fazer um fork e modificá-lo, tenho certeza que pode ser otimizado.https://gist.github.com/ryanmjacobs/4c02ad80f833dee0c307
Responder4
Escrevi algumas funções simples baseadas na melhor resposta que produzirão a saída no formato desejado.
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
}
Uso/exemplo:
$ generate_permutations foobar
{f,F}{o,O}{o,O}{b,B}{a,A}{r,R}