Programing

Bash에서 배열을 정렬하는 방법

crosscheck 2020. 7. 12. 09:54
반응형

Bash에서 배열을 정렬하는 방법


예를 들어 Bash에 배열이 있습니다.

array=(a c b f 3 5)

배열을 정렬해야합니다. 내용을 정렬 된 방식으로 표시 할뿐만 아니라 정렬 된 요소를 사용하여 새 배열을 가져옵니다. 새로운 정렬 된 배열은 완전히 새로운 배열이거나 오래된 배열 일 수 있습니다.


실제로 그렇게 많은 코드가 필요하지는 않습니다.

IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS

지원 (한이 줄 바꿈이 아니라으로) 요소의 공백, 그리고 배쉬 3.x에서의 작업

예 :

$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]

참고 : @sorontar이있다 지적 요소와 같은 와일드 카드가 포함 된 경우 치료가 필요하다는 것을 *?:

sorted = ($ (...)) 부분은 "split and glob"연산자를 사용하고 있습니다. 당신은 글로브을 끄고해야 set -f또는 set -o noglob또는 shopt -op noglob또는 같은 배열의 요소 *파일 목록으로 확장됩니다.

무슨 일이야:

결과는 다음 순서로 발생하는 6 가지 결과입니다.

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<
  4. sort
  5. sorted=($(...))
  6. unset IFS

먼저 IFS=$'\n'

이는 다음과 같은 방식으로 2와 5의 결과에 영향을 미치는 운영의 중요한 부분입니다.

주어진:

  • "${array[*]}" 첫 문자로 구분 된 모든 요소로 확장 IFS
  • sorted=() 의 모든 문자를 분할하여 요소를 만듭니다 IFS

IFS=$'\n' 새 줄 을 구분 기호로 사용하여 요소를 확장 한 다음 나중에 각 줄이 요소가되는 방식으로 만들어 지도록 설정합니다 . (즉, 새 줄로 나누기)

새로운 라인으로 구분하는 것이 중요합니다. 왜냐하면 그것이 sort운영 방식 (라인 당 정렬) 이기 때문입니다 . 새 줄 만으로 분할하는 것은 중요하지 않지만 공백이나 탭이 포함 된 요소를 유지해야합니다.

기본값 IFSspace , tab , 그 뒤에 새 줄로 표시 되며 작업에 적합하지 않습니다.

다음 sort <<<"${array[*]}"부분

<<<여기에서 strings 이라고 "${array[*]}"하는는 위에서 설명한대로 의 확장을 가져 와서의 표준 입력에 공급합니다 sort.

이 예에서는 sort다음 문자열이 제공됩니다.

a c
b
f
3 5

때문에 sort 종류 , 그것은 생산 :

3 5
a c
b
f

다음 sorted=($(...))부분

$(...)라는 부분, 명령 치환은 , 그 내용 (원인 sort <<<"${array[*]}결과하면서, 일반 명령으로 실행)를 표준 출력 지금 어디가는 그 문자 등을 $(...)했다.

이 예에서는 단순히 쓰기와 비슷한 것을 생성합니다.

sorted=(3 5
a c
b
f
)

sorted 그런 다음 모든 리터럴에서이 리터럴을 분할하여 생성 된 배열이됩니다.

마지막으로 unset IFS

이는의 값을 IFS기본값으로 재설정하며 좋은 방법입니다.

IFS나중에 스크립트 에 의존하는 어떤 문제도 발생하지 않도록하기위한 것입니다 . (그렇지 않으면 복잡한 스크립트에는 실용적이지 않은 것들을 바꿔 놓았다는 것을 기억해야합니다.)


원래 답변 :

array=(a c b "f f" 3 5)
readarray -t sorted < <(for a in "${array[@]}"; do echo "$a"; done | sort)

산출:

$ for a in "${sorted[@]}"; do echo "$a"; done
3
5
a
b
c
f f

참고 (특수 문자 나 공백을 포함하는 값이 버전의 대처를 제외하고 줄 바꿈)

참고 readarray는 bash 4 이상에서 지원됩니다.


@Dimitre의 제안에 따라 편집 했습니다.

readarray -t sorted < <(printf '%s\0' "${array[@]}" | sort -z | xargs -0n1)

개행 문자가 올바르게 포함 된 정렬 요소를 이해하는 이점도 있습니다. 불행히도 @ruakh가 올바르게 신호를 보낸다고해서 바꿈 문자일반 바꿈 대신 사용할 옵션이 없기 때문에 결과 readarray정확 하다는 의미는 아닙니다 .readarrayNUL


순수한 Bash 퀵 정렬 구현은 다음과 같습니다.

#!/bin/bash

# quicksorts positional arguments
# return is in array qsort_ret
qsort() {
   local pivot i smaller=() larger=()
   qsort_ret=()
   (($#==0)) && return 0
   pivot=$1
   shift
   for i; do
      if [[ $i < $pivot ]]; then
         smaller+=( "$i" )
      else
         larger+=( "$i" )
      fi
   done
   qsort "${smaller[@]}"
   smaller=( "${qsort_ret[@]}" )
   qsort "${larger[@]}"
   larger=( "${qsort_ret[@]}" )
   qsort_ret=( "${smaller[@]}" "$pivot" "${larger[@]}" )
}

예를 들어,

$ array=(a c b f 3 5)
$ qsort "${array[@]}"
$ declare -p qsort_ret
declare -a qsort_ret='([0]="3" [1]="5" [2]="a" [3]="b" [4]="c" [5]="f")'

이 구현은 재귀 적입니다. 따라서 반복적 인 퀵 정렬이 있습니다 :

#!/bin/bash

# quicksorts positional arguments
# return is in array qsort_ret
# Note: iterative, NOT recursive! :)
qsort() {
   (($#==0)) && return 0
   local stack=( 0 $(($#-1)) ) beg end i pivot smaller larger
   qsort_ret=("$@")
   while ((${#stack[@]})); do
      beg=${stack[0]}
      end=${stack[1]}
      stack=( "${stack[@]:2}" )
      smaller=() larger=()
      pivot=${qsort_ret[beg]}
      for ((i=beg+1;i<=end;++i)); do
         if [[ "${qsort_ret[i]}" < "$pivot" ]]; then
            smaller+=( "${qsort_ret[i]}" )
         else
            larger+=( "${qsort_ret[i]}" )
         fi
      done
      qsort_ret=( "${qsort_ret[@]:0:beg}" "${smaller[@]}" "$pivot" "${larger[@]}" "${qsort_ret[@]:end+1}" )
      if ((${#smaller[@]}>=2)); then stack+=( "$beg" "$((beg+${#smaller[@]}-1))" ); fi
      if ((${#larger[@]}>=2)); then stack+=( "$((end-${#larger[@]}+1))" "$end" ); fi
   done
}

두 경우 모두 사용 순서를 변경할 수 있습니다. 문자열 비교를 사용했지만 산술 비교, wrt 파일 수정 시간 비교 등을 수행 할 수 있습니다. 적절한 테스트 만 사용하십시오. 좀 더 일반적인 것으로 만들 수도 있고 테스트 함수가 사용하는 첫 번째 인수를 사용할 수도 있습니다.

#!/bin/bash

# quicksorts positional arguments
# return is in array qsort_ret
# Note: iterative, NOT recursive! :)
# First argument is a function name that takes two arguments and compares them
qsort() {
   (($#<=1)) && return 0
   local compare_fun=$1
   shift
   local stack=( 0 $(($#-1)) ) beg end i pivot smaller larger
   qsort_ret=("$@")
   while ((${#stack[@]})); do
      beg=${stack[0]}
      end=${stack[1]}
      stack=( "${stack[@]:2}" )
      smaller=() larger=()
      pivot=${qsort_ret[beg]}
      for ((i=beg+1;i<=end;++i)); do
         if "$compare_fun" "${qsort_ret[i]}" "$pivot"; then
            smaller+=( "${qsort_ret[i]}" )
         else
            larger+=( "${qsort_ret[i]}" )
         fi
      done
      qsort_ret=( "${qsort_ret[@]:0:beg}" "${smaller[@]}" "$pivot" "${larger[@]}" "${qsort_ret[@]:end+1}" )
      if ((${#smaller[@]}>=2)); then stack+=( "$beg" "$((beg+${#smaller[@]}-1))" ); fi
      if ((${#larger[@]}>=2)); then stack+=( "$((end-${#larger[@]}+1))" "$end" ); fi
   done
}

그런 다음이 비교 기능을 가질 수 있습니다.

compare_mtime() { [[ $1 -nt $2 ]]; }

그리고 사용 :

$ qsort compare_mtime *
$ declare -p qsort_ret

현재 폴더의 파일을 수정 시간순으로 정렬합니다 (가장 먼저).

노트. 이 기능은 순수한 배쉬입니다! 외부 유틸리티도없고 서브 쉘도 없습니다! 그것들은 당신이 가질 수있는 재미있는 기호 (공백, 줄 바꿈 문자, 글로브 문자 등)로 안전합니다.


배열 요소에서 특수 쉘 문자를 처리 할 필요가없는 경우 :

array=(a c b f 3 5)
sorted=($(printf '%s\n' "${array[@]}"|sort))

bash사용 하면 외부 정렬 프로그램이 필요합니다.

zsh를 사용하면 외부 프로그램이 필요하지 않으며 특수 쉘 문자를 쉽게 처리 할 수 ​​있습니다.

% array=('a a' c b f 3 5); printf '%s\n' "${(o)array[@]}" 
3
5
a a
b
c
f

kshASCIIset -s 로 정렬 해야 합니다.


뮌헨에서 프랑크푸르트까지 3 시간의 기차 여행에서 (내일 옥토버 페스트가 시작되기 때문에 연락이 어려웠습니다) 첫 번째 게시물에 대해 생각하고있었습니다. 전역 정렬을 사용하는 것이 일반적인 정렬 기능에 훨씬 좋습니다. 다음 함수는 임의의 문자열 (줄 바꿈, 공백 등)을 처리합니다.

declare BSORT=()
function bubble_sort()
{   #
    # @param [ARGUMENTS]...
    #
    # Sort all positional arguments and store them in global array BSORT.
    # Without arguments sort this array. Return the number of iterations made.
    #
    # Bubble sorting lets the heaviest element sink to the bottom.
    #
    (($# > 0)) && BSORT=("$@")
    local j=0 ubound=$((${#BSORT[*]} - 1))
    while ((ubound > 0))
    do
        local i=0
        while ((i < ubound))
        do
            if [ "${BSORT[$i]}" \> "${BSORT[$((i + 1))]}" ]
            then
                local t="${BSORT[$i]}"
                BSORT[$i]="${BSORT[$((i + 1))]}"
                BSORT[$((i + 1))]="$t"
            fi
            ((++i))
        done
        ((++j))
        ((--ubound))
    done
    echo $j
}

bubble_sort a c b 'z y' 3 5
echo ${BSORT[@]}

인쇄합니다 :

3 5 a b c z y

동일한 출력이

BSORT=(a c b 'z y' 3 5) 
bubble_sort
echo ${BSORT[@]}

아마도 Bash는 내부적으로 스마트 포인터를 사용하므로 스왑 작업 저렴 할 수 있습니다 (의심 할지라도). 그러나 bubble_sort보다 고급 기능 merge_sort도 쉘 언어에 도달 할 수 있음을 보여줍니다 .


tl; dr :

배열을 정렬 a_in하고 결과를 저장하십시오 a_out(요소에는 개행 문자 포함되어 있지 않아야 함 [1] ).

배쉬 v4 + :

readarray -t a_out < <(printf '%s\n' "${a_in[@]}" | sort)

배쉬 v3 :

IFS=$'\n' read -d '' -r -a a_out < <(printf '%s\n' "${a_in[@]}" | sort)

antak 솔루션의 장점 :

  • 실수로 글 로빙 (배열 요소를 파일 이름 패턴으로 우발적으로 해석)하는 것에 대해 걱정할 필요가 없으므로 글 로빙을 비활성화하기 위해 추가 명령이 필요하지 않습니다 ( set -f, set +f나중에 복원).

  • 로 재설정 IFS대해 걱정할 필요가 없습니다 unset IFS. [2]


읽기 옵션 : 설명 및 샘플 코드

위의 내용은 Bash 코드와 외부 유틸리티 sort결합 하여 임의의 한 줄 요소어휘 또는 숫자 정렬 (선택적으로 필드 별)함께 작동 하는 솔루션을 제공 합니다 .

  • 성능 : 들어 약 20 원소 이상 ,이 될 것입니다 빠른 순수 배쉬 솔루션보다 - 상당히 점점 그래서 당신은 약 100 요소를 넘어 일단.
    (정확한 임계 값은 특정 입력, 기계 및 플랫폼에 따라 다릅니다.)

    • 빠른 이유 는 Bash 루프를 피하기 때문 입니다.
  • printf '%s\n' "${a_in[@]}" | sort 정렬을 수행합니다 (기본적으로 기본적으로 sortPOSIX 사양 참조 ).

    • "${a_in[@]}"안전하게 배열의 요소로 확장 a_in등의 개별 인수 가 (공백 포함)를 포함 무엇이든.

    • printf '%s\n' 그런 다음 각 인수, 즉 각 배열 요소를 자체 줄에 그대로 인쇄합니다.

  • 노트 (A)의 사용 방법 치환 ( <(...)) 에 대한 입력으로 정렬 된 출력을 제공 read/를 readarray(표준 입력으로 재 통해 <때문에) read/은 readarray실행해야 현재 (a 실행 안 하부 쉘 출력 변수의 순서) a_out가 볼 수 있도록 변수를 스크립트의 나머지 부분에 정의 된 상태로 유지하려면 현재 셸에 추가하십시오.

  • sort의 결과를 배열 변수읽기 :

    • Bash v4 + : 각 요소 의 후행 포함하지 않고 readarray -t a_out개별 행 출력 sort을 array variable 요소로 읽습니다 ( ).a_out\n-t

    • 배시 V3 : readarray그래서없는 read사용해야는 :
      IFS=$'\n' read -d '' -r -a a_out지시 read(배열로 읽을 -a) 변수 a_out라인 (통해, 전체 입력을 읽는 -d ''), 그러나 바꿈에 의한 배열 요소로 분할하여 ( IFS=$'\n'. $'\n'리터럴 개행을 생성하는 (LF를 )는 소위 ANSI C 인용 문자열입니다 ).
      ( -r거의 항상와 함께 사용해야하는 옵션 read은 예기치 않은 \문자 처리를 비활성화합니다 .)

주석이 달린 샘플 코드 :

#!/usr/bin/env bash

# Define input array `a_in`:
# Note the element with embedded whitespace ('a c')and the element that looks like
# a glob ('*'), chosen to demonstrate that elements with line-internal whitespace
# and glob-like contents are correctly preserved.
a_in=( 'a c' b f 5 '*' 10 )

# Sort and store output in array `a_out`
# Saving back into `a_in` is also an option.
IFS=$'\n' read -d '' -r -a a_out < <(printf '%s\n' "${a_in[@]}" | sort)
# Bash 4.x: use the simpler `readarray -t`:
# readarray -t a_out < <(printf '%s\n' "${a_in[@]}" | sort)

# Print sorted output array, line by line:
printf '%s\n' "${a_out[@]}"

sort옵션없이 사용 하면 어휘 정렬 (문자 앞의 숫자 정렬 및 숫자 시퀀스가 ​​숫자가 아닌 어휘 적으로 처리됨)이 생성됩니다.

*
10
5
a c
b
f

첫 번째 필드를 기준으로 숫자 정렬 을 원할 경우 sort -k1,1njust 대신에를 사용 sort하면 숫자가 아닌 숫자가 숫자보다 먼저 정렬되고 숫자가 올바르게 정렬됩니다.

*
a c
b
f
5
10

[1] 줄 바꿈이 포함 된 요소를 처리하려면 다음 변형 ( GNU 와 함께 Bash v4 + sort)을 사용하십시오
readarray -d '' -t a_out < <(printf '%s\0' "${a_in[@]}" | sort -z).
Michał Górny의 유용한 답변 에는 Bash v3 솔루션이 있습니다.

하면서 2] IFS 된다 배시 V3 변이체 설정, 변경이되는 명령에 범위 .
대조적으로, IFS=$'\n' antak의 대답에서 따르는 것은 명령이 아닌 할당 이며,이 경우 IFS변경은 전역 적 입니다.


외부 사용하는 다른 솔루션 sort과 및 대처 어떤 (:) NUL을 제외) 특수 문자를. bash-3.2 및 GNU 또는 BSD와 함께 작동해야합니다 sort(슬프게도 POSIX에는 포함되지 않음 -z).

local e new_array=()
while IFS= read -r -d '' e; do
    new_array+=( "${e}" )
done < <(printf "%s\0" "${array[@]}" | LC_ALL=C sort -z)

먼저 입력 리디렉션을 살펴보십시오. printf내장 요소를 사용하여 0으로 끝나는 배열 요소를 작성합니다. 인용 부호를 사용하면 배열 요소를 그대로 전달할 수 있으며 쉘의 특성으로 printf인해 나머지 각 매개 변수에 대해 형식 문자열의 마지막 부분을 재사용 할 수 있습니다. 즉, 다음과 같습니다.

for e in "${array[@]}"; do
    printf "%s\0" "${e}"
done

그런 다음 널 종료 요소 목록이로 전달됩니다 sort. -z옵션을 사용하면 Null로 끝나는 요소를 읽고 정렬하고 Null로 끝나는 결과를 출력합니다. 고유 한 요소 만 -u가져와야하는 경우보다 이동성이 뛰어나 므로 전달할 수 있습니다 uniq -z. LC_ALL=C로케일 독립적으로 안정적인 정렬 순서를 보장 - 스크립트를 때로는 유용하다. 당신이 원하는 경우 sort로케일 존중, 그것을 제거합니다.

<()구조체는 스폰 파이프 라인으로부터 판독하는 디스크립터를 획득하고, <의 표준 입력 리디렉션 while그것을 루프. 파이프 내부의 표준 입력에 액세스해야하는 경우 다른 설명자 (독자 연습)를 사용할 수 있습니다.

이제 처음으로 돌아갑니다. read내장은 리디렉션 된 표준 입력에서 출력을 읽습니다. 공란으로 설정 IFS하면 단어 분리가 비활성화되어 여기서 불필요합니다. 결과적 read으로 입력 된 전체 '라인'을 단일 제공된 변수로 읽습니다. -r옵션은 여기서 바람직하지 않은 이스케이프 처리를 비활성화합니다. 마지막으로 -d ''줄 구분 기호를 NUL로 설정합니다. 즉, read0으로 끝나는 문자열을 읽습니다.

결과적으로 루프는 연속적인 0으로 끝나는 모든 배열 요소에 대해 한 번 실행되며 값은에 저장됩니다 e. 이 예에서는 항목을 다른 배열에 넣지 만 직접 처리하는 것이 좋습니다. :).

물론 그것은 동일한 목표를 달성하는 많은 방법 중 하나 일뿐입니다. 보시다시피, bash에서 완전한 정렬 알고리즘을 구현하는 것보다 간단하며 경우에 따라 더 빠릅니다. 개행을 포함한 모든 특수 문자를 처리하며 대부분의 일반 시스템에서 작동합니다. 가장 중요한 것은 bash에 대해 새롭고 멋진 것을 가르쳐 줄 수 있습니다. :).


이 시도:

echo ${array[@]} | awk 'BEGIN{RS=" ";} {print $1}' | sort

출력은 다음과 같습니다.


5
에프

문제 해결됨.


최소 정렬 :

#!/bin/bash
array=(.....)
index_of_element1=0

while (( ${index_of_element1} < ${#array[@]} )); do

    element_1="${array[${index_of_element1}]}"

    index_of_element2=$((index_of_element1 + 1))
    index_of_min=${index_of_element1}

    min_element="${element_1}"

        for element_2 in "${array[@]:$((index_of_element1 + 1))}"; do
            min_element="`printf "%s\n%s" "${min_element}" "${element_2}" | sort | head -n+1`"      
            if [[ "${min_element}" == "${element_2}" ]]; then
                index_of_min=${index_of_element2}
            fi
            let index_of_element2++
        done

        array[${index_of_element1}]="${min_element}"
        array[${index_of_min}]="${element_1}"

    let index_of_element1++
done

다음과 같이 배열의 각 요소에 대해 고유 한 정수를 계산할 수있는 경우 :

tab='0123456789abcdefghijklmnopqrstuvwxyz'

# build the reversed ordinal map
for ((i = 0; i < ${#tab}; i++)); do
    declare -g ord_${tab:i:1}=$i
done

function sexy_int() {
    local sum=0
    local i ch ref
    for ((i = 0; i < ${#1}; i++)); do
        ch="${1:i:1}"
        ref="ord_$ch"
        (( sum += ${!ref} ))
    done
    return $sum
}

sexy_int hello
echo "hello -> $?"
sexy_int world
echo "world -> $?"

Bash는 항상 희소 배열을 사용하므로 사용하지 않는 인덱스에 대해 걱정할 필요가 없으므로 이러한 정수를 배열 인덱스로 사용할 수 있습니다.

array=(a c b f 3 5)
for el in "${array[@]}"; do
    sexy_int "$el"
    sorted[$?]="$el"
done

echo "${sorted[@]}"
  • 찬성 빠른.
  • 단점 중복 된 요소가 병합되어 내용을 32 비트 고유 정수로 매핑하는 것이 불가능할 수 있습니다.

array=(a c b f 3 5)
new_array=($(echo "${array[@]}" | sed 's/ /\n/g' | sort))    
echo ${new_array[@]}

new_array의 에코 내용은 다음과 같습니다.

3 5 a b c f

Bash에서 외부 정렬 프로그램이 필요하다고 확신하지 않습니다.

다음은 간단한 버블 정렬 알고리즘에 대한 구현입니다.

function bubble_sort()
{   #
    # Sorts all positional arguments and echoes them back.
    #
    # Bubble sorting lets the heaviest (longest) element sink to the bottom.
    #
    local array=($@) max=$(($# - 1))
    while ((max > 0))
    do
        local i=0
        while ((i < max))
        do
            if [ ${array[$i]} \> ${array[$((i + 1))]} ]
            then
                local t=${array[$i]}
                array[$i]=${array[$((i + 1))]}
                array[$((i + 1))]=$t
            fi
            ((i += 1))
        done
        ((max -= 1))
    done
    echo ${array[@]}
}

array=(a c b f 3 5)
echo " input: ${array[@]}"
echo "output: $(bubble_sort ${array[@]})"

이것은 다음을 인쇄합니다 :

 input: a c b f 3 5
output: 3 5 a b c f

a=(e b 'c d')
shuf -e "${a[@]}" | sort >/tmp/f
mapfile -t g </tmp/f

공백과 줄 바꾸기의 일반적인 문제에 대한 해결 방법이 있습니다.

원래의 배열 (같은 아닌 문자를 사용 $'\1'하거나 $'\4'또는 유사한).

이 함수는 작업을 수행합니다.

# Sort an Array may have spaces or newlines with a workaround (wa=$'\4')
sortarray(){ local wa=$'\4' IFS=''
             if [[ $* =~ [$wa] ]]; then
                 echo "$0: error: array contains the workaround char" >&2
                 exit 1
             fi

             set -f; local IFS=$'\n' x nl=$'\n'
             set -- $(printf '%s\n' "${@//$nl/$wa}" | sort -n)
             for    x
             do     sorted+=("${x//$wa/$nl}")
             done
       }

이것은 배열을 정렬합니다 :

$ array=( a b 'c d' $'e\nf' $'g\1h')
$ sortarray "${array[@]}"
$ printf '<%s>\n' "${sorted[@]}"
<a>
<b>
<c d>
<e
f>
<gh>

소스 배열에 해결 방법 문자가 포함되어 있다고 불평합니다.

$ array=( a b 'c d' $'e\nf' $'g\4h')
$ sortarray "${array[@]}"
./script: error: array contains the workaround char

기술

  • 두 개의 로컬 변수 wa(해결 방법 char)와 null IFS를 설정했습니다.
  • 그런 다음 (if null이있는 경우) 전체 배열을 테스트합니다 $*.
  • woraround char이 포함되어 있지 않습니다 [[ $* =~ [$wa] ]].
  • 그렇다면 메시지를 표시하고 오류를 표시하십시오. exit 1
  • 파일 이름 확장을 피하십시오. set -f
  • IFS=$'\n'루프 변수 x와 개행 변수 var ( nl=$'\n') 를 IFS ( ) 의 새 값으로 설정하십시오 .
  • 수신 된 인수 (입력 배열 $@) 의 모든 값을 인쇄합니다 .
  • 그러나 해결 방법 char으로 새 줄을 바꿉니다 "${@//$nl/$wa}".
  • 정렬 할 값을 보냅니다 sort -n.
  • 정렬 된 모든 값을 위치 인수에 다시 넣습니다 set --.
  • 그런 다음 각 인수를 하나씩 지정하여 줄 바꿈을 유지합니다.
  • 루프에서 for x
  • 새로운 배열로 : sorted+=(…)
  • 기존의 개행을 유지하기 위해 따옴표 안에 넣습니다.
  • 해결 방법을 개행으로 복원합니다 "${x//$wa/$nl}".
  • 끝난

sorted=($(echo ${array[@]} | tr " " "\n" | sort))

bash / linux의 정신으로 각 단계마다 최상의 명령 줄 도구를 파이프합니다. sort주요 작업을 수행하지만 공간 대신 ​​줄 바꿈으로 구분 된 입력이 필요하므로 위의 매우 간단한 파이프 라인은 단순히 다음을 수행합니다.

에코 배열 내용-> 줄 바꾸기로 공간 바꾸기-> 정렬

$() 결과를 에코하는 것입니다

($()) "반향 된 결과"를 배열에 넣는 것입니다

참고 : @sorontar 가 다른 질문 에 대한 주석 에서 언급 한 것처럼 :

sorted = ($ (...)) 부분은 "split and glob"연산자를 사용하고 있습니다. glob를 해제해야합니다. set -f 또는 set -o noglob 또는 shopt -op noglob 또는 *와 같은 배열 요소는 파일 목록으로 확장됩니다.

참고 URL : https://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-bash

반응형