Split a string by separators into an array

Solved
romegonic Posted messages 29 Status Member -  
romegonic Posted messages 29 Status Member -
Hello,

I am using korn shell on AIX.

Let's take a string (coming from a line in a file, via sed):
chaine='nom_1:valeur_1,nom_2:valeur_2,nom_3:valeur_3,nom_3:valeur_3'

I want to loop through this string and fill an array, using ',' as the delimiter.

This way, I can capture the name and its value and take care of truncating the ':' to use these two fields.

The idea is to be able to then call tab[3], which would be nom_3 and its valeur_3.

The additional difficulty lies in the fact that the size of the string is, of course, not fixed, as is the number of "records".

Thus the array size cannot be defined in advance.

If someone could help me, I'm struggling with just the usual sed, cut, awk, tr.
It's mainly at the loop level that I am having trouble, as there are quite a few examples regarding input files, but very few concerning strings (and I am not going to write my string into a file... which would make one line, providing no real benefit...).

A while end of string? A for i in 'echo $chaine' do .. ?

Thank you in advance for any responses you may have.

Configuration: Windows 7 / Chrome 33.0.1750.154

5 answers

  1. zipe31 Posted messages 34620 Registration date   Status Contributor Last intervention   6 501
     
    Hello,

    I use korn shell on AIX.

    Is ksh necessary? ;-\

    Because otherwise, in bash:

    $ chaine='nom_1:valeur_1,nom_2:valeur_2,nom_3:valeur_3,nom_3:valeur_3'

    $ echo "${chaine}"
    nom_1:valeur_1,nom_2:valeur_2,nom_3:valeur_3,nom_3:valeur_3

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

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

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

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

    --
    Zen my nuggets ;-)
    Do something for the environment, close your windows and adopt a penguin. <('')
    1
    1. dindoun Posted messages 1047 Status Member 135
       
      super I didn't know tab=(${chaine//,/ })
      1
  2. Anonymous user
     
    Hello,

    with mksh, on 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
    Note: arrays are zero-indexed by default; therefore, to access the first element of the array, you need to call
    "$tab[0]}"
    ;)
    0
    1. Anonymous user
       
      une 'tite correction :
      "${tab[0]}"
      : 'was missing a brace, phew.
      0
  3. romegonic Posted messages 29 Status Member
     
    Thank you for your responses.

    The first solution doesn't work under ksh (too bad it was clean and easy to manipulate afterwards).
    As for the second, I'm getting a syntax error (via set -xv) on the line:
    IFS=',' read -A tab <<<"$chaine"

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

    basically, it doesn't expect three <<< in a row (and if I remove one, it does nothing)

    I'm continuing to search via awk, in any case thanks for the effort.
    0
  4. zipe31 Posted messages 34620 Registration date   Status Contributor Last intervention   6 501
     
    Using the example of qqchqcpQ and the same interpreter (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 'Name = %s\tValue = %s\n' "${tab[$i]%:*}" "${tab[$i]#*:}"
    ((i++))
    done

    $ ./foo.mksh
    Name = nom_1 Value = valeur_1
    Name = nom_2 Value = valeur_2
    Name = nom_3 Value = valeur_3
    Name = nom_4 Value = valeur_4


    --
    Zen my nuggets ;-)
    Make a gesture for the environment, close your windows and adopt a penguin. <('')
    0
  5. romegonic Posted messages 29 Status Member
     
    Hello,

    I finally opted for the following code, using arrays, as I wanted:

    (previously I loaded the string into the object variable)

    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


    And this is very handy to use for replacing a value corresponding to a name :-)

    Issue resolved, thank you for your help :-)
    0