¿Matrices en unix shell?

Respuestas:

90

El siguiente código crea e imprime una matriz de cadenas en shell:

#!/bin/bash
array=("A" "B" "ElementC" "ElementE")
for element in "${array[@]}"
do
    echo "$element"
done

echo
echo "Number of elements: ${#array[@]}"
echo
echo "${array[@]}"

Resultado:

A
B
ElementC
ElementE

Number of elements: 4

A B ElementC ElementE
Vincent Agami
fuente
61

en bash, creas una matriz como esta

arr=(one two three)

llamar a los elementos

$ echo "${arr[0]}"
one
$ echo "${arr[2]}"
three

para solicitar información del usuario, puede usar read

read -p "Enter your choice: " choice
ghostdog74
fuente
La declaración separada por espacios NO funciona para /bin/sharrojar un error line 1: syntax error: unexpected "(". ¿Conoces alguna alternativa?
mhyousefi
20

El shell Bourne no admite matrices. Sin embargo, hay dos formas de manejar el problema.

Utilice los parámetros de shell posicionales $ 1, $ 2, etc .:

$ set one two three
$ echo $*
one two three
$ echo $#
3
$ echo $2
two

Utilice evaluaciones de variables:

$ n=1 ; eval a$n="one" 
$ n=2 ; eval a$n="two" 
$ n=3 ; eval a$n="three"
$ n=2
$ eval echo \$a$n
two
Mishka
fuente
1
Bash admite matrices. No estoy seguro sobre el shell Bourne original, pero bash es más frecuente en estos días ...
plesiv
2
@zplesivcak - ... en GNU / Linux, ya que es una cosa GNU. Por ejemplo, FreeBSD no se envía con bash(aunque se puede instalar desde los puertos). Los scripts escritos asumiendo que las bashcaracterísticas no son portátiles, y son notablemente más lentos que la mayoría de las implementaciones de shell Bourne (como dash, que es común en las distribuciones GNU / Linux). bashes un shell interactivo agradable, pero es lento para la creación de scripts.
beatgammit
1
$*se considera perjudicial. Normalmente, $@se prefiere ya que hace lo mismo, pero mantiene espacios. $@se expande como "$ 1" "$ 2" "$ 3" ... "$ n", mientras que $*se expande como "$ 1x $ 2x $ 3x ... $ n", donde xes un $IFSseparador (lo más probable, espacio).
zserge
1
Sin comillas, $@es lo mismo que $*; la diferencia solo aparece cuando se cita: "$*"es una palabra, mientras que "$@"conserva los saltos de palabras originales.
Mark Reed
La pregunta está etiquetada bash, por lo que las respuestas específicas de bash son apropiadas, pero es cierto que no se debe asumir que /bin/shes bash.
Mark Reed
13
#!/bin/bash

# define a array, space to separate every item
foo=(foo1 foo2)

# access
echo "${foo[1]}"

# add or changes
foo[0]=bar
foo[2]=cat
foo[1000]=also_OK

Puede leer la "Guía avanzada de scripts de bash" de ABS

Lai Jiangshan
fuente
3
Por favor, reconsidere la sugerencia de ABS como un recurso de aprendizaje: de muchas maneras critica lo que es W3Schools para HTML y Javascript, tiene mucho jugo de Google pero muestra malas prácticas en muchos de sus ejemplos, y rara vez e inadecuadamente actualizado. El wiki de bash-hackers es un recurso mucho mejor; también lo es BashGuide .
Charles Duffy
La declaración separada por espacios NO funciona para /bin/sharrojar un error line 1: syntax error: unexpected "(". ¿Conoces alguna alternativa?
mhyousefi
8

El shell Bourne y el shell C no tienen matrices, IIRC.

Además de lo que otros han dicho, en Bash puede obtener la cantidad de elementos en una matriz de la siguiente manera:

elements=${#arrayname[@]}

y hacer operaciones de estilo de corte:

arrayname=(apple banana cherry)
echo ${arrayname[@]:1}                   # yields "banana cherry"
echo ${arrayname[@]: -1}                 # yields "cherry"
echo ${arrayname[${#arrayname[@]}-1]}    # yields "cherry"
echo ${arrayname[@]:0:2}                 # yields "apple banana"
echo ${arrayname[@]:1:1}                 # yields "banana"
Pausado hasta nuevo aviso.
fuente
csh tiene matrices.
Keith Thompson
@KeithThompson: No está documentado en la página de manual, pero la funcionalidad parece estar presente en al menos algunas versiones.
Pausado hasta nuevo aviso.
3
La página de manual no menciona "matrices" con ese nombre, pero consulte la documentación del setcomando ( set name=(wordlist)) y la sección "Sustitución de variables" ( $name[selector]y ${name[selector]}). Hasta donde yo sé, csh siempre ha admitido matrices. Vea, por ejemplo, la $pathvariable de matriz, que refleja la $PATHvariable de entorno.
Keith Thompson
8

Prueba esto :

echo "Find the Largest Number and Smallest Number of a given number"
echo "---------------------------------------------------------------------------------"
echo "Enter the number"
read n
i=0

while [ $n -gt 0 ] #For Seperating digits and Stored into array "x"
do
        x[$i]=`expr $n % 10`
        n=`expr $n / 10`
        i=`expr $i + 1`
done

echo "Array values ${x[@]}"  # For displaying array elements


len=${#x[*]}  # it returns the array length


for (( i=0; i<len; i++ ))    # For Sorting array elements using Bubble sort
do
    for (( j=i+1; j<len;  j++ ))
    do
        if [ `echo "${x[$i]} > ${x[$j]}"|bc` ]
        then
                t=${x[$i]}
                t=${x[$i]}
                x[$i]=${x[$j]}
                x[$j]=$t
        fi
        done
done


echo "Array values ${x[*]}"  # Displaying of Sorted Array


for (( i=len-1; i>=0; i-- ))  # Form largest number
do
   a=`echo $a \* 10 + ${x[$i]}|bc`
done

echo "Largest Number is : $a"

l=$a  #Largest number

s=0
while [ $a -gt 0 ]  # Reversing of number, We get Smallest number
do
        r=`expr $a % 10`
        s=`echo "$s * 10 + $r"|bc`
        a=`expr $a / 10`
done
echo "Smallest Number is : $s" #Smallest Number

echo "Difference between Largest number and Smallest number"
echo "=========================================="
Diff=`expr $l - $s`
echo "Result is : $Diff"


echo "If you try it, We can get it"
muthukrishnavinayagam
fuente
Esto solo funciona en ksh y bash, ¿verdad?
Lassi
6

Su pregunta se refiere a "secuencias de comandos de shell de Unix", pero está etiquetada bash. Esas son dos respuestas diferentes.

La especificación POSIX para shells no tiene nada que decir sobre los arreglos, ya que el shell Bourne original no los admitía. Incluso hoy en día, en FreeBSD, Ubuntu Linux y muchos otros sistemas, /bin/shno tiene soporte para arreglos. Entonces, si desea que su script funcione en diferentes shells compatibles con Bourne, no debe usarlos. Alternativamente, si está asumiendo un shell específico, asegúrese de poner su nombre completo en la línea shebang, por ejemplo #!/usr/bin/env bash.

Si está utilizando bash o zsh , o una versión moderna de ksh , puede crear una matriz como esta:

myArray=(first "second element" 3rd)

y acceder a elementos como este

$ echo "${myArray[1]}"
second element

Puede obtener todos los elementos a través de "${myArray[@]}". Puede usar la notación de sector $ {matriz [@]: inicio: longitud} para restringir la parte de la matriz a la que se hace referencia, por ejemplo, "${myArray[@]:1}"para dejar el primer elemento.

La longitud de la matriz es ${#myArray[@]}. Puede obtener una nueva matriz que contenga todos los índices de una matriz existente con "${!myArray[@]}".

Las versiones anteriores de ksh anteriores a ksh93 también tenían matrices, pero no la notación basada en paréntesis, ni admitían la división. Sin embargo, podría crear una matriz como esta:

set -A myArray -- first "second element" 3rd 
Mark Reed
fuente
5

Puede probar el siguiente tipo:

#!/bin/bash
 declare -a arr

 i=0
 j=0

  for dir in $(find /home/rmajeti/programs -type d)
   do
        arr[i]=$dir
        i=$((i+1))
   done


  while [ $j -lt $i ]
  do
        echo ${arr[$j]}
        j=$((j+1))
  done
Roopesh Majeti
fuente
se rompe en los nombres de directorio con espacios. use un bucle while read de change IFS para encargarse de eso.
ghostdog74
5

Una matriz se puede cargar de dos formas.

set -A TEST_ARRAY alpha beta gamma

o

X=0 # Initialize counter to zero.

- Cargue la matriz con las cadenas alfa, beta y gamma

for ELEMENT in alpha gamma beta
do
    TEST_ARRAY[$X]=$ELEMENT
    ((X = X + 1))
done

Además, creo que la siguiente información puede ayudar:

El shell admite matrices unidimensionales. El número máximo de elementos de la matriz es 1024. Cuando se define una matriz, se dimensiona automáticamente a 1024 elementos. Una matriz unidimensional contiene una secuencia de elementos de la matriz, que son como los vagones conectados entre sí en una vía de tren.

En caso de que desee acceder a la matriz:

echo ${MY_ARRAY[2] # Show the third array element
 gamma 


echo ${MY_ARRAY[*] # Show all array elements
-   alpha beta gamma


echo ${MY_ARRAY[@] # Show all array elements
 -  alpha beta gamma


echo ${#MY_ARRAY[*]} # Show the total number of array elements
-   3


echo ${#MY_ARRAY[@]} # Show the total number of array elements
-   3

echo ${MY_ARRAY} # Show array element 0 (the first element)
-  alpha
Pinaki Mukherjee
fuente
4

Si desea una tienda de valor clave con soporte para espacios, use el -Aparámetro:

declare -A programCollection
programCollection["xwininfo"]="to aquire information about the target window."

for program in ${!programCollection[@]}
do
    echo "The program ${program} is used ${programCollection[${program}]}"
done

http://linux.die.net/man/1/bash "Las matrices asociativas se crean usando declare -A name."

richardjsimkins
fuente
4

Hay varias formas de crear una matriz en shell.

ARR[0]="ABC"
ARR[1]="BCD"
echo ${ARR[*]}

${ARR[*]} imprime todos los elementos de la matriz.

La segunda forma es:

ARR=("A" "B" "C" "D" 5 7 "J")
echo ${#ARR[@]}
echo ${ARR[0]}

${#ARR[@]} se utiliza para contar la longitud de la matriz.

Manjotsingh Chug
fuente
Buena respuesta, gran comienzo para un novato. Y bienvenido a los niveles de
votos positivos
3

Para leer los valores del teclado e insertar el elemento en la matriz

# enter 0 when exit the insert element
echo "Enter the numbers"
read n
while [ $n -ne 0 ]
do
    x[$i]=`expr $n`
    read n
    let i++
done

#display the all array elements
echo "Array values ${x[@]}"
echo "Array values ${x[*]}"

# To find the array length
length=${#x[*]}
echo $length
paraca
fuente
1

En ksh lo haces:

set -A array element1 element2 elementn

# view the first element
echo ${array[0]}

# Amount elements (You have to substitute 1)
echo ${#array[*]}

# show last element
echo ${array[ $(( ${#array[*]} - 1 )) ]}
usuario224243
fuente
Una forma más concisa de mostrar el último elemento es echo "${array[@]:(-1)}". Esto elimina la necesidad de escribir dos veces el nombre de la variable de matriz.
Alex Dupuy
1

Una forma sencilla:

arr=("sharlock"  "bomkesh"  "feluda" )  ##declare array

len=${#arr[*]}  #determine length of array

# iterate with for loop
for (( i=0; i<len; i++ ))
do
    echo ${arr[$i]}
done
rashedcs
fuente