小文字/大文字の単語のすべての可能な組み合わせを取得します

小文字/大文字の単語のすべての可能な組み合わせを取得します

特定の単語(例:harley)の小文字と大文字のすべての可能な順列を出力する bash スクリプトを書きたいです。

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 "{}"

どうしても1行に1語ずつ入れなければならない場合は、

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'

楽しみのために、「ハーレー」を次のように置き換えてみてください「スーパーカリフラジリスティックエクスピアリドーシャス」5分経ちましたが、私のコンピューターはまだこれを処理中で、おそらく終わらないでしょう:)

答え2

eval echo $(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 の組み合わせが生成されないはずです。

編集:理由は分かりませんが、この解決策は本当に@Joeseph R による Perl ソリューションに比べて高速です。「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}

関連情報