私のスクリプトは次の設定を使用します。
#!/bin/bash
array=(C G D A E B)
if [[ "$1" = "--setstart" ]] || [[ "$1" = "-s" ]]; then
if [ -n "$2" ]; then
array=($(sed "s/.*$2 /$2 /" <<< "${array[@]}"))
else
printf "\nno argument...!\n"
fi
fi
for a in "${array[@]}"; do
printf "%s " "$a"
done
echo
この--setstart
オプションを使用すると、配列の読み取りを開始する場所を選択できます(このsed
コマンドは、現在この問題を解決するために私が考えることができる唯一の方法です)。
スクリプト自体はprints:オプションなしで実行され、C G D A E B
値を設定すると--setstart
その時点で配列を印刷するため、--setstart D
print:doesですD A E B
。
array
最初に切り取った部分が最後まで入るように、これをループに印刷するオプションをどのように導入しますか?設定がD
印刷されたと仮定すると:D A E B C G
?
答え1
Bashサブストリング(サブ配列)拡張を使用する(例:${parameter:offset:length}
)...
array=(A B C D E F)
start=$1
# handle negative offsets
[[ $start -lt 0 ]] && start=$((${#array[@]} + start))
# the star of the show, create array2 from two sub-arrays of array
array2=("${array[@]:$start}" "${array[@]:0:$start}")
echo "${array2[@]}"
ここでは、説明のために元の配列を新しく配置された配列に配置します。 (いくつかの明らかな境界検査などを省略しました。)
$ ./rotate.sh 3
D E F A B C
修正する:負のオフセットを処理するために上記のスクリプトを修正しました。イカチュウの答え)...
$ ./rotate.sh -2
E F A B C D
アップデート2:「A」から「F」までの文字の1つ(質問の例とより密接に一致する)を許可するスクリプトの場合は、次のようstart=$1
に置き換えます。
# Convert [A-F] to ASCII code then normalize to [0-5]
LC_CTYPE=C start=$(( $(printf %d "'$1") - 65 ))
もちろん、ソートされた文字配列がない場合は、任意の配列要素を処理するために次のようなものが必要です。
idx=0
for elem in "${array[@]}"; do
[[ $elem = $1 ]] && break
((idx++))
done
start=$idx
答え2
モジュラスを使用します。クン/クッシュ:
$ cat rotate.sh
#!/bin/bash
array=(A B C D E F)
n=${#array[@]}
start=${1-0}
i=0;
while (( i < n )) ; do
printf "%s " "${array[(start + i) % n]}"
(( i++ ))
done
echo
Zsh は 1 で配列インデックスを開始するので、少し調整が必要です。最初のコマンドラインパラメータは開始位置を設定し、負の数にすることがstart
できます。
$ ./rotate.sh 2
C D E F A B
値で始点を見つけるには、修正が簡単でなければなりません。