Separar una cadena mediante separadores, hacia una matriz

Resuelto
romegonic Mensajes publicados 29 Estado Miembro -  
romegonic Mensajes publicados 29 Estado Miembro -
Hola,

Estoy usando KornShell en AIX.

Pongamos una cadena de caracteres (proveniente de una línea de un archivo, vía sed):
cadena='nom_1:valor_1,nom_2:valor_2,nom_3:valor_3,nom_3:valor_3'

Quiero recorrer esta cadena y rellenar un arreglo, indicando como delimitador la ','.

Así voy a capturar el nombre y su valor y me encargo de truncar el ':' para usar estos dos campos.

La idea es poder después llamar tab[3], es decir el nom_3 y valor_3.

La dificultad adicional es que el tamaño de la cadena no es fijo, y tampoco el número de "registros" que contiene.

Por tanto, el tamaño del arreglo no puede definirse de antemano.

Si alguien pudiera ayudarme, no me manejo solo con los habituales sed, cut, awk, tr. Es sobre todo en la parte del bucle que estoy atascado, ya que hay muchos ejemplos para archivos de entrada, pero pocos para cadenas (y no voy a copiar mi cadena en un archivo... que fuera una sola línea, lo cual no aportaría nada...).

¿Un while fin de cadena? ¿Un for i in 'echo $cadena' do .. ?

Gracias de antemano por cualquier respuesta.

Configuración: Windows 7 / Chrome 33.0.1750.154

5 respuestas

  1. zipe31 Mensajes publicados 34620 Fecha de registro   Estado Colaborador Última intervención   6 502
     
    Hola,

    Estoy usando Korn shell en AIX.

    ¿Es obligatorio ksh? ;-\

    Porque si no en bash:

    $ cadena='nom_1:valor_1,nom_2:valor_2,nom_3:valor_3,nom_3:valor_3' 

    $ echo "${cadena}"
    nom_1:valor_1,nom_2:valor_2,nom_3:valor_3,nom_3:valor_3

    $ tab=(${cadena//,/ })

    $ echo ${tab[2]}
    nom_3:valor_3

    $ echo ${tab[2]%:*}
    nom_3

    $ echo ${tab[2]#*:}
    valor_3

    --
    Zen mes nuggets ;-)
    Faites un geste pour l'environnement, fermez vos fenêtres et adoptez un manchot. <('')
    1
    1. dindoun Mensajes publicados 1047 Estado Miembro 135
       
      super, no conocía tab=(${cadena//,/ })
      1
  2. Usuario anónimo
     
    hola,

    con mksh, en Debian
    $ chaine='nom_1:valeur_1,nom_2:valeur_2,nom_3:valeur_3,nom_3:valeur_3'
    $ IFS=',' read -A tab <<<"$chaine"
    $ printf '%s\n' "$tab[@]}"
    nom_1:valeur_1
    nom_2:valeur_2
    nom_3:valeur_3
    nom_3:valeur_3
    NB: les tableaux, par défaut, sont indexés à partir de zéro; donc, pour accéder au premier élément du tableau, il faut appeler
    "$tab[0]}"
    ;)
    0
    1. Usuario anónimo
       
      una pequeña corrección:
      "<${tab[0]}>"
      : faltaba una llave, uf.
      0
  3. romegonic Mensajes publicados 29 Estado Miembro
     
    Gracias por vuestras respuestas.

    La primera solución no funciona bajo ksh (una lástima, era limpia y fácil de manipular después).
    En cuanto a la segunda, me encuentro con un error (con set -xv) de sintaxis en la línea:
    IFS=',' read -A tab <<<"$chaine"

    IFS=',' read -A tab <<<"./aps.sh[23]: syntax error at line 23 : '<' unexpected

    en resumen no espera tres <<< de forma consecutiva (y si quito uno ya no hace nada)

    Sigo buscando a través de awk, en cualquier caso gracias por el esfuerzo.
    0
  4. zipe31 Mensajes publicados 34620 Fecha de registro   Estado Colaborador Última intervención   6 502
     
    En reprenant l'exemple de qqchqcpQ et le même interpréteur (mksh) :

    $ cat foo.mksh
    #! /bin/mksh

    chaine='nom_1:valeur_1,nom_2:valeur_2,nom_3:valeur_3,nom_4:valeur_4'
    IFS=',' read -A tab <<<"$chaine"

    i=0
    for j in "${tab[@]}"
    do
    printf 'Nom = %s\tValeur = %s\n' "${tab[$i]%:*}" "${tab[$i]#*:}"
    ((i++))
    done

    $ ./foo.mksh
    Nom = nom_1 Valeur = valeur_1
    Nom = nom_2 Valeur = valeur_2
    Nom = nom_3 Valeur = valeur_3
    Nom = nom_4 Valeur = valeur_4


    --
    Zen my nuggets ;-)
    Faites un geste pour l'environnement, fermez vos fenêtres et adoptez un manchot. <('')
    0
  5. romegonic Mensajes publicados 29 Estado Miembro
     
    Hola, He acabado optando por el siguiente código, utilizando tablas, como quería: (anteriormente cargué la cadena en la variable objeto)
    nb_att_objet='echo $objet | awk -F ',' '{ print NF }'' set -A attribut_nom; set -A attribut_valeur for i in 'seq 1 $nb_att_objet'; do attribut_nom[$i]='echo $objet | cut -d "," -f${i} | awk -F "\"" '{ print $2 }''; attribut_valeur[$i]='echo $objet | cut -d "," -f${i} | awk -F "\"" '{ print $4 }''; done
    Y esto es muy práctico para reemplazar un valor que corresponde a un nombre :-) Asunto resuelto, gracias por tu ayuda :-)
    0