답변:
작성된 질문에 대답 했으며이 코드는 배열을 반대로 바꿉니다. (배열을 반전시키지 않고 요소를 역순으로 인쇄하는 for
것은 마지막 요소에서 0으로 카운트 다운 하는 루프 일뿐 입니다.) 이것은 표준 "첫 번째와 마지막 스왑"알고리즘입니다.
array=(1 2 3 4 5 6 7)
min=0
max=$(( ${#array[@]} -1 ))
while [[ min -lt max ]]
do
# Swap current first and last elements
x="${array[$min]}"
array[$min]="${array[$max]}"
array[$max]="$x"
# Move closer
(( min++, max-- ))
done
echo "${array[@]}"
홀수 및 짝수 길이의 배열에서 작동합니다.
또 다른 비 전통적인 접근 방식 :
#!/bin/bash
array=(1 2 3 4 5 6 7)
f() { array=("${BASH_ARGV[@]}"); }
shopt -s extdebug
f "${array[@]}"
shopt -u extdebug
echo "${array[@]}"
산출:
7 6 5 4 3 2 1
경우 extdebug
활성화되어 배열 BASH_ARGV
역순 모든 위치 매개 변수 함수로 포함한다.
비 전통적인 접근 방식 (모두 순수하지 않음 bash
) :
배열의 모든 요소가 하나의 문자 (질문과 같이) 인 경우 다음을 사용할 수 있습니다 rev
.
echo "${array[@]}" | rev
그렇지 않으면:
printf '%s\n' "${array[@]}" | tac | tr '\n' ' '; echo
그리고 당신이 사용할 수 있다면 zsh
:
echo ${(Oa)array}
tac
의 반대로서 cat
, 감사를 기억하는 아주 좋은!
rev
것을 언급해야합니다 rev
. 예를 들어 12
rev 를 사용 하는 배열 요소 는로 인쇄됩니다 21
. 그것을 시도하십시오 ;-)
실제로 다른 배열에서 반전을 원할 경우 :
reverse() {
# first argument is the array to reverse
# second is the output array
declare -n arr="$1" rev="$2"
for i in "${arr[@]}"
do
rev=("$i" "${rev[@]}")
done
}
그때:
array=(1 2 3 4)
reverse array foo
echo "${foo[@]}"
제공합니다 :
4 3 2 1
이것은 배열 인덱스가없는 경우를 올바르게 처리해야합니다 (예 array=([1]=1 [2]=2 [4]=4)
: 0에서 최상위 인덱스로 루핑하면 빈 요소가 추가 될 수 있습니다).
shellcheck
두 가지 경고가 인쇄 되지만 다음 array=(1 2 3 4)
<-- SC2034: array appears unused. Verify it or export it.
과 같은 경고가 표시 됩니다.echo "${foo[@]}"
<-- SC2154: foo is referenced but not assigned.
declare
.
declare -n
4.3 이전의 bash 버전에서는 작동하지 않는 것 같습니다.
배열 위치를 적절한 위치로 교체하려면 (bash 배열 이후에도) (bash 3.0부터) :
#!/bin/bash
# Declare an sparse array to test:
array=([5]=101 [6]=202 [10]=303 [11]=404 [20]=505 [21]=606 [40]=707)
echo "Initial array values"
declare -p array
swaparray(){ local temp; temp="${array[$1]}"
array[$1]="${array[$2]}"
array[$2]="$temp"
}
ind=("${!array[@]}") # non-sparse array of indexes.
min=-1; max="${#ind[@]}" # limits to one before real limits.
while [[ min++ -lt max-- ]] # move closer on each loop.
do
swaparray "${ind[min]}" "${ind[max]}" # Exchange first and last
done
echo "Final Array swapped in place"
declare -p array
echo "Final Array values"
echo "${array[@]}"
실행시 :
./script
Initial array values
declare -a array=([5]="101" [6]="202" [10]="303" [11]="404" [20]="505" [21]="606" [40]="707")
Final Array swapped in place
declare -a array=([5]="707" [6]="606" [10]="505" [11]="404" [20]="303" [21]="202" [40]="101")
Final Array values
707 606 505 404 303 202 101
오래된 bash의 경우 루프 (bash에서 (2.04 이후))를 사용 $a
하고 후행 공백을 피하기 위해 사용해야합니다 .
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a=""
for (( i=last-1 ; i>=0 ; i-- ));do
printf '%s%s' "$a" "${array[i]}"
a=" "
done
echo
2.03 이후 bash의 경우 :
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a="";i=0
while [[ last -ge $((i+=1)) ]]; do
printf '%s%s' "$a" "${array[ last-i ]}"
a=" "
done
echo
또한 (비트 부정 연산자 사용) (bash 4.2 이상부터) :
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a=""
for (( i=0 ; i<last ; i++ )); do
printf '%s%s' "$a" "${array[~i]}"
a=" "
done
echo
미운, 유지 불가능하지만 하나의 라이너 :
eval eval echo "'\"\${array['{$((${#array[@]}-1))..0}']}\"'"
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'"
.
ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
비록 새로운 것을 말하지 않고 tac
배열을 뒤집는 데 사용할 것입니다.하지만 bash 버전 4.4를 사용하는 다음 단일 라인 솔루션을 언급 할 가치가 있습니다.
$ read -d'\n' -a array < <(printf '%s\n' "${array[@]}" |tac)
테스트 :
$ array=(1 2 3 4 5 6 10 11 12)
$ echo "${array[@]}"
1 2 3 4 5 6 10 11 12
$ read -d'\n' -a array < <(printf '%s\n' "${array[@]}"|tac)
$ echo "${array[@]}"
12 11 10 6 5 4 3 2 1
읽은 var 이름은 원래 배열의 이름이므로 임시 저장소에는 도우미 배열이 필요하지 않습니다.
IFS를 조정하여 대체 구현 :
$ IFS=$'\n' read -d '' -a array < <(printf '%s\n' "${array[@]}"|tac);declare -p array
declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")
추신 : 위의 솔루션은 bash 내장 함수 구현이 다르기 때문에 bash
아래 버전 에서 작동하지 않는다고 생각 합니다.4.4
read
IFS
버전은 작동하지만 그것은 또한 인쇄된다 declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12")
. bash 사용 4.4-5
. ;declare -p array
첫 번째 줄의 끝에서 제거 해야합니다. 그러면 작동합니다.
declare -p
는 bash가 실제 배열 (인덱스 및 내용)을 인쇄하는 빠른 방법입니다. declare -p
실제 스크립트에는 이 명령 이 필요하지 않습니다 . 배열 할당에서 문제가 발생하면 ${array[0]}="1 2 3 4 5 6 10 11 12"
= = 모든 값이 동일한 인덱스에 저장된 경우 echo를 사용하면 차이가 없습니다. 빠른 배열 인쇄물을 사용 declare -p array
하면 실제 색인 및 각 색인의 해당 값이 반환됩니다.
read -d'\n'
방법은 당신을 위해 작동하지 않았다?
read -d'\n'
잘 작동합니다.
임의의 배열을 뒤집으려면 (값을 가진 여러 요소를 포함 할 수 있음) :
로 zsh
:
array_reversed=("${(@Oa)array}")
로 bash
4.4, 주어진 bash
변수는 GNU를 사용하여, NUL 어쨌든 바이트를 포함 할 수 없습니다 tac -s ''
NUL 레코드를 구분으로 인쇄 된 요소 :
readarray -td '' array_reversed < <(
((${#array[@]})) && printf '%s\0' "${array[@]}" | tac -s '')
POSIXly 상기 POSIX 쉘 어레이 반전 ( $@
만들어진를 $1
, $2
...) :
code='set --'
n=$#
while [ "$n" -gt 0 ]; do
code="$code \"\${$n}\""
n=$((n - 1))
done
eval "$code"
순수한 bash 솔루션은 하나의 라이너로 작동합니다.
$: for (( i=${#array[@]}-1; i>=0; i-- ))
> do rev[${#rev[@]}]=${array[i]}
> done
$: echo "${rev[@]}"
7 6 5 4 3 2 1
rev+=( "${array[i]}" )
것이 더 간단 해 보입니다.
당신은 또한 사용을 고려할 수 있습니다 seq
array=(1 2 3 4 5 6 7)
for i in $(seq $((${#array[@]} - 1)) -1 0); do
echo ${array[$i]}
done
freebsd에서 -1 증가 매개 변수를 생략 할 수 있습니다.
for i in $(seq $((${#array[@]} - 1)) 0); do
echo ${array[$i]}
done
array=(1 2 3 4 5 6 7)
echo "${array[@]} " | tac -s ' '
또는
array=(1 2 3 4 5 6 7)
reverse=$(echo "${array[@]} " | tac -s ' ')
echo ${reverse[@]}
7 6 5 4 3 2 1
$ tac --version
tac (GNU coreutils) 8.28