
我想編寫一個 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
對應的可擴展版本是:
echo harley \
| perl -nle 'print join "",map { "{" . lc . "," .uc ."}" } split //' \
| xargs -I {} bash -c 'for w in {};do echo $w;done'
為了好玩,試著將“harley”替換為“超級加州脆弱性Expialidocious”已經 5 分鐘了,我的電腦仍在處理這個問題,可能永遠無法完成:)
答案2
評估迴聲$(迴聲“單字" | sed 's/./{\U&,\L&}/g')
sed 's/./{&,&}/g'
會Foo
變成{F,F}{o,o}{o,o}
,這將是毫無用處的。但是加上\U
and\L
就可以得到每個字母的大寫和小寫; IE,{F,f}{O,o}{O,o}
。eval
然後就是使用告訴 shell 展開 {的簡單問題X,X大括號序列。
答案3
編輯2:這個答案是錯的。它不會產生應有的 2^n 組合。
編輯:我不知道為什麼,但這個解決方案是真的與 @Joeseph R 的 perl 解決方案相比,速度更快。
這是我的破解方法:
#!/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
請隨意 fork 和修改它,我相信它可以被優化。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}