내 스크립트에서는 다음 설정을 사용합니다.
#!/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"까지의 문자 중 하나(질문의 예와 더 밀접하게 일치)를 허용하는 스크립트의 경우 다음 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
값별로 시작점을 찾으려면 수정이 간단해야 합니다.