Bashで配列をソートできる関数を作成するには?

Bashで配列をソートできる関数を作成するには?

配列をパラメータとして受け取り、ソートできる関数を作成する方法を見つけようとしています。位置変数で行われているようですが、わかりません。

答え1

強く打つ

bashまだ組み込みのサポートがないようです。オプションは、ソートアルゴリズムを手動で実装するか、sortソートアルゴリズムを呼び出すことです。

配列要素にゼロ以外のすべてのバイト値を含めることができると思われる場合、bashこれを確実に実行するには、NULで区切られた要素のリストを渡し、オプション-zsort非標準ですがGNUソートまたはFreeBSDソートで使用可能)を使用する必要があります。

bash-4.4(2016年9月リリース)では、区切り文字を指定する-dオプションを組み込みに導入して、作業をより簡単にします。readarray

配列aを配列で並べ替えますb

readarray -td '' b < <(printf '%s\0' "${a[@]}" | sort -z)

配列は安定して整列されます。数値順または逆順(またはサポートされている並べ替え条件)で並べ替えるには-n、オプションを使用します。-rsortsort

関数を実装するにはsortarray(引数として渡されたすべての配列を名前でソート):

sortarray() for array do
  eval '((${#'"$array"'[@]} <= 1))' || readarray -td '' "$array" < <(
    eval "printf '%s\0' \"\${$array[@]}\" | sort -z")
done

以前のバージョンでは、ループ内で同じことを実行bashできます。read -d

b=()
while IFS= read -rd '' item; do b+=("$item"); done < <(
  printf '%s\0' "${a[@]}" | sort -z)

機能の場合sortarray

sortarray() for array do eval '
  tmp=()
  while IFS= read -rd "" item; do tmp+=("$item"); done < <(
    printf "%s\0" "${'"$array"'[@]}" | sort -z)
  '"$array"'=("${tmp[@]}")'
done

扱いにくい

Zshには配列整列機能が組み込まれています。

oパラメータ拡張フラグを使用して、語彙的に(O逆順に)ソートできます。n数値順に並べ替えるためにフラグを追加できます。

$ a=('' 12 2 d é f $'a\nb')
$ printf '<%s>\n' "${(@o)a}"
<>
<12>
<2>
<a
b>
<d>
<é>
<f>
$ printf '<%s>\n' "${(@no)a}"
<>
<2>
<12>
<a
b>
<d>
<é>
<f>

まだ大文字と小文字を区別するソート機能がないロケールでは、これにiフラグを追加することもできます。

配列に割り当てる:

b=("${(@o)a}")

したがって、sortarray関数は次のようになります。

sortarray() for array do eval "$array=(\"\${(@o)$array}\")"; done

AT&T ksh

set -s -- "${a[@]}"
b=("$@")

set -sパラメータリストを並べ替えて、位置パラメータに保存します。順序は語彙的です。

機能はsortarray次のとおりです。

sortarray() for array do
  eval 'set -s -- "${'"$array"'[@]}"; '"$array"'=("$@")'
done

答え2

簡単なソートのために、以下を使用してくださいsorttr

arr=($(for i in {0..9}; do echo $((RANDOM%100)); done))
echo ${arr[*]}| tr " " "\n" | sort -n | tr "\n" " "

新しい配列として:

arr2=($(echo ${arr[*]}| tr " " "\n" | sort -n))

tr/の助けを借りずにsort、例えばバブルソート:

#!/bin/bash    
sort () {
    for ((i=0; i <= $((${#arr[@]} - 2)); ++i))
    do
        for ((j=((i + 1)); j <= ((${#arr[@]} - 1)); ++j))
        do
            if [[ ${arr[i]} -gt ${arr[j]} ]]
            then
                # echo $i $j ${arr[i]} ${arr[j]}
                tmp=${arr[i]}
                arr[i]=${arr[j]}
                arr[j]=$tmp         
            fi
        done
    done
}
# arr=(6 5 68 43 82 60 45 19 78 95)
arr=($(for i in {0..9}; do echo $((RANDOM%100)); done))
echo ${arr[@]}
sort ${arr[@]}
echo ${arr[@]}

20個の数字の場合は、バブルソートで十分です。

答え3

sortnums(){
    local OLDPWD IFS=' /'
    cd -- "$(mktemp -d)" || return
    touch -- $*;  ls -A
    cd - >/dev/null &&
    rm -rf -- "$OLDPWD"
}

以下は少し複雑で遅いバージョンですが、重複項目を圧縮せずにソートを実行します。(適切なサイズ)数字順に小数 - 段(空間分割)他の文字列はまだ文字列の長さを最初に考慮してソートされています。通常の文字列を処理するには、ほぼ確実にg=[0-9]globを異なる設定にしたいと思います。

私は真実を言うでしょう - 私は言うでしょう(おそらく)リストの並べ替えを検討してください。性格または数字ですが、少なくとも段落に合わない名前でファイルを作るつもりはありません。だから空間的に分かれています。ほとんどの場合、これは正しいことです。しかし、/これをnullのように処理しなければならないという健全な要件によって妨げられることもあります。しかしとにかくそれはただ楽しみのためのものです。

fs_sort(){
        local OLDPWD IFS=' /' opt="$-" g
        cd -- "$(mktemp -d)" || return
        set     -C                         ### noClobber for testable >
        for     g in    $*                 ### disallow any / reference
        do      until   command >" $g"     ### who needs dot glob?
                do      g=" $g"            ### '   1' lex== ' 1'
        done;   done    2>&1               ### -C is bitchy
                g=[0-9]                    ### now glob the array
        while   set -f *\ $g   &&          ### set it  &&
                <"$1" g+=? arr+=( $* )     ### <chk && (clean) it
        do      set +f;    done 2>&1       ### clear it
        set +fC "-${opts:--}"              ### put stuff where we found it
        cd - && rm  -rf -- "$OLDPWD"       ### don't leave our trash out
}       >/dev/null                         ### cd - is chatty

ここに教訓がある場合は、おそらく最初にbash配列がどれほど汚れているかを理解する必要があります。データが保存されたばかり文書sort私たちは当初、何の問題もありません。ログインシェルが小さな部分だけをクロールする場合は、必要なときに重要なシェル状態を維持する方がはるかに簡単になります。一時ファイルシステム起動時に~/.shディレクトリをここにコピーし、終了後に固定されているとマークされているすべてのファイルを再度コピーします。みんなあなたの週名前単にソートされ、set *他のファイルと同様に、呼び出したいユーティリティからその内容にアクセスできます。

答え4

#! /bin/bash

array=('2' '7' '5' '9' '0')
sort=0
echo ${array[@]}
len=${#array[@]}
echo $len


for ((i=0; i<$len; i++))
do
    for((j=i+1; j<$len; j++))
    do
        if [ ${array[i]} -le ${array[j]} ]
        then
            continue
        else
            sort=${array[i]}
            array[i]=${array[j]}
            array[j]=$sort
        fi
    done
done
echo ${array[@]}

関連情報