Shell-Script

查找數組元素組合的 shell 腳本

  • July 13, 2020

我有一個 shell 腳本,我在其中定義了一個數組。該數組包含超過 2 個元素。我需要找到數組中所有元素的組合。假設,如果我的數組有元素,,*{12345, 56789, 98765}*我試圖得到輸出,

12345, 56789
12345, 98765
56789, 98765

我從這裡嘗試了 php 程式碼。

<?php
function pc_permute($items, $perms = array( )) {
   if (empty($items)) {
       print join(' ', $perms) . "\n";
   }  else {
       for ($i = count($items) - 1; $i >= 0; --$i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            pc_permute($newitems, $newperms);
        }
   }
}
pc_permute(split(' ', '12345 56789 98765'));
?>

我得到的輸出為,

12345 56789 98765
56789 12345 98765
12345 98765 56789
98765 12345 56789
56789 98765 12345
98765 56789 12345

是否可以在 2 個元素大小的輸出中獲得組合?我不關心順序,所以如果*A B作為組合得到,我不需要反向(B A*)。

你所需要的只是——這就是printf.它的print function工作。

printf '%s\t%s\n' ${array[@]}

你這樣做:

( set -- 12345 56789 98765; for i ; do 
   eval set -- $(printf '"$%s" ' `seq 2 $#` 1)
   echo "$*"
done )

輸出

56789 98765 12345
98765 12345 56789
12345 56789 98765

我不需要eval——那太愚蠢了。這是一個更好的:

( set -- 12345 56789 98765 ; 
until [ $((i=i+1)) -gt $# ] ; do
   set -- $(s=$1 ; shift ; printf '%s\n' "$@" "$s")
   printf '%s ' "$@" ; echo
done)

輸出

56789 98765 12345
98765 12345 56789
12345 56789 98765

然後,如果您只想要兩個元素,您只需稍微更改一下 - 再增加一行:

( set -- 12345 56789 98765 ;
   until [ $((i=i+1)) -ge $# ] ; do
       set -- $(s=$1 ; shift ; printf '%s\n' "$@" "$s")
       v="${v}$(printf '%s ' "$@")"
   done ; printf "%s\t%s\n" $v
   )

輸出

56789   98765
12345   98765
12345   56789

我一直都這樣做,但從來沒有過這種行為。我總是使用真正的 shell 數組,所以需要幾分鐘才能掌握它。

這是我為另一個答案寫的一個小腳本:

   abc="a b c d e f g h i j k l m n o p q r s t u v w x y z"
for l in $abc ; do { 
       h= c= ; [ $((i=i+1)) -gt 26 ] && n=$((n+26)) i=
   xyz=$(x=${xyz:-$abc} ;\
       printf %s\\n ${x#?} $l)
   mid=$(set -- $xyz ; eval echo \$$((${#}/4))) ;\
       echo "$mid $l" >&2 ;
       [ $(((i+n)%${mod=3})) -eq 0 ] && c="$mid" h="${xyz%"$mid"*}"
   line="$(printf '%s ' $h $c ${xyz#"$h"})"
   printf "%s$(printf %s ${xyz#?}${mid})\n" \
       ${line} >|/tmp/file$((i+n))
} ; done

這將寫入 26 個文件。它們看起來像這樣,只是它們在每個文件中遞增:

bcdefghijklmnopqrstuvwxyzag
ccdefghijklmnopqrstuvwxyzag
dcdefghijklmnopqrstuvwxyzag
ecdefghijklmnopqrstuvwxyzag
fcdefghijklmnopqrstuvwxyzag
gcdefghijklmnopqrstuvwxyzag
hcdefghijklmnopqrstuvwxyzag
icdefghijklmnopqrstuvwxyzag
jcdefghijklmnopqrstuvwxyzag
kcdefghijklmnopqrstuvwxyzag
lcdefghijklmnopqrstuvwxyzag
mcdefghijklmnopqrstuvwxyzag
ncdefghijklmnopqrstuvwxyzag
ocdefghijklmnopqrstuvwxyzag
pcdefghijklmnopqrstuvwxyzag
qcdefghijklmnopqrstuvwxyzag
rcdefghijklmnopqrstuvwxyzag
scdefghijklmnopqrstuvwxyzag
tcdefghijklmnopqrstuvwxyzag
ucdefghijklmnopqrstuvwxyzag
vcdefghijklmnopqrstuvwxyzag
wcdefghijklmnopqrstuvwxyzag
xcdefghijklmnopqrstuvwxyzag
ycdefghijklmnopqrstuvwxyzag
zcdefghijklmnopqrstuvwxyzag
acdefghijklmnopqrstuvwxyzag

引用自:https://unix.stackexchange.com/questions/123800