各要素の部分文字列に基づいて配列をソートする

各要素の部分文字列に基づいて配列をソートする

各要素の部分文字列に基づいて配列をソートするにはどうすればよいでしょうか?
例えば次のような配列があるとします

arr=( 2some05stuff 4more02stuff 3evenmore01stuff 1no04stuff )

要素を先頭の数値文字列で並べ替えたいstuffので、次のようになります。

3evenmore01stuff
4more02stuff
1no04stuff
2some05stuff

パラメータ拡張フラグoO配列の順序変更は知っています。

-rl に "${(@on)arr}" と印刷します。
1no04stuff
2some05stuff
3evenmore01stuff
4more02stuff

そして

-rl に "${(@On)arr}" と印刷します。
4more02stuff
3evenmore01stuff
2some05stuff
1no04stuff

これらのフラグを関数や他のパラメータ拡張(例えば、添え字の削除や添え字の拡張など)と組み合わせることが可能かどうかはわかりません...

答え1

これをインラインで行う方法はわかりません。 globs 修飾子を使用すると、ソート キー ( *(oe\''REPLY=${${REPLY%stuff*}##*[^0-9]}'\')) を指定できますが、パラメーター拡張修飾子ではそのようなことはできません。

実行できることは${sort_key}$'\0'${value}、 を含む補助配列を構築することです。つまり、ソート キーに null バイトと元の値を追加します。ソート キーに null バイトが含まれていないと仮定すると、その配列をソートすると目的の順序が得られ、ソート キーのプレフィックスを削除すると目的の結果が得られます。

typeset -a tmp; tmp=(); typeset -i i
for ((i=1; i<=$#arr; i++)); do tmp[$i]=${${arr[$i]%stuff*}##*[^0-9]}$'\0'$arr[$i]; done
print -lr "${(@)${(@o)tmp}#*$'\0'}"

関連情報