配列をパラメータとして受け取り、ソートできる関数を作成する方法を見つけようとしています。位置変数で行われているようですが、わかりません。
答え1
強く打つ
bash
まだ組み込みのサポートがないようです。オプションは、ソートアルゴリズムを手動で実装するか、sort
ソートアルゴリズムを呼び出すことです。
配列要素にゼロ以外のすべてのバイト値を含めることができると思われる場合、bash
これを確実に実行するには、NULで区切られた要素のリストを渡し、オプション-z
(sort
非標準ですがGNUソートまたはFreeBSDソートで使用可能)を使用する必要があります。
bash-4.4(2016年9月リリース)では、区切り文字を指定する-d
オプションを組み込みに導入して、作業をより簡単にします。readarray
配列a
を配列で並べ替えますb
。
readarray -td '' b < <(printf '%s\0' "${a[@]}" | sort -z)
配列は安定して整列されます。数値順または逆順(またはサポートされている並べ替え条件)で並べ替えるには-n
、オプションを使用します。-r
sort
sort
関数を実装するには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
簡単なソートのために、以下を使用してくださいsort
。tr
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[@]}