Saltar al contenido

Cómo crear una función que pueda ordenar un array en bash?

[*]este problema se puede resolver de variadas formas, sin embargo te dejamos la respuesta más completa para nosotros.

Solución:

intento

[*]No creo bash tiene algún soporte incorporado para eso todavía. Las opciones serían implementar un algoritmo de clasificación a mano o invocar sort para hacer la clasificación.

[*]Si consideramos que array Los elementos pueden contener cualquier valor de byte pero 0 en bash, para hacerlo de manera confiable, tendríamos que pasar la lista de elementos delimitados por NUL y usar el -z opción a sort (no estándar pero disponible en tipo GNU o tipo FreeBSD).

[*]bash-4.4 (lanzado en septiembre de 2016) lo hace más fácil ya que introdujo un -d opción a su readarray incorporado para especificar el delimitador.

[*]Para ordenar array a en array b:

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

[*]ordenaría el array seguramente. Utilizar el -n, -r opciones para sort para ordenar numéricamente o al revés (o cualquier criterio de clasificación apoyado por sort).

[*]Para implementar su sortarray función (ordena todas las matrices pasadas por nombre como argumentos):

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

[*]Con versiones anteriores de bash, puedes usar read -d en un bucle para lograr lo mismo:

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

[*]Para el sortarray función:

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

zsh

[*]Zsh tiene soporte integrado para ordenar matrices.

[*]puedes usar el o bandera de expansión de parámetros para ordenar léxicamente (O para orden inverso). Puede agregar el n bandera para ordenar numéricamente:

$ a=('' 12 2 d é f $'anb')
$ printf '<%s>n' "$(@o)a"
<>
<12>
<2>


<é>

$ printf '<%s>n' "$(@no)a"
<>
<2>
<12>


<é>

[*]En las configuraciones regionales que aún no clasifican de forma independiente a mayúsculas y minúsculas, también puede agregar la i bandera para eso.

[*]Para asignar a un array:

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

[*]Entonces un sortarray la función sería como:

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

AT&T ksh (ksh88 o ksh93, ambos se pueden encontrar como sh en algunos sistemas)

set -s -- "$a[@]"
b=("[email protected]")

[*]set -s ordena la lista de argumentos y la almacena en los parámetros posicionales. El orden es léxico.

[*]A sortarray la función podría ser:

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

[*]Ordene de la manera más fácil con sort, tr:

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

[*]En un nuevo array:

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

[*]Sin ayuda de tr/sort, por ejemplo, bubblesort:

#!/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[@]

[*]Para 20 números, la clasificación por burbujas puede ser suficiente.

sortnums() return
    touch -- $*;  ls -A
    cd - >/dev/null &&
    rm -rf -- "$OLDPWD"

[*]Aquí hay una versión un poco más complicada y algo más lenta que, sin embargo, no aprieta los duplicados y que ordena (de tamaño razonable) números decimales en orden numérico, aunque (espacio dividido) otras cadenas todavía están ordenadas, string la longitud se considera primero. Y para manejar cadenas genéricas, es casi seguro que querrás configurar el g=[0-9] glob de manera diferente.

[*]Seré honesto, lo haría (quizás) considere ordenar una lista de palabras o números como este, pero de otra manera no se me ocurriría crear un archivo con un nombre que al menos no encajaría cómodamente dentro de un párrafo. Y entonces se divide en espacios. La mayoría de las veces, eso es lo correcto. Sin embargo, también se ve obstaculizado por un requisito de cordura de tratar / como un null. Pero fue solo por diversión, de todos modos, de verdad.

fs_sort()
        local OLDPWD IFS=' /' opt="$-" g
        cd -- "$(mktemp -d)"        >/dev/null                         ### cd - is chatty

[*]Si hay alguna lección en esto, tal vez debería ser lo sucio que son las matrices bash en primer lugar. Si los datos simplemente se mantuvieran en archivos nunca tendríamos ningún problema sortinglo en primer lugar. Imagínese cuánto más fácil sería mantener un estado importante de shell cuando fuera necesario si sus shells de inicio de sesión solo tomaran una pequeña parte de tmpfs al inicio, copió un ~/.sh directorio en él, y luego copie de nuevo cualquier archivo que haya marcado como pegajoso desde que se apagó. Todo de tu estado nombres ordenaría tan simplemente como set *, y su contenido sería accesible para cualquier utilidad a la que quisiera llamarlos, como lo es cualquier otro archivo.

Sección de Reseñas y Valoraciones

[*]

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *