2 votes

KSH scripting : comment séparer sur ',' quand les valeurs ont des virgules échappées ?

J'essaie d'écrire un script KSH pour traiter un fichier constitué de paires nom-valeur, dont plusieurs sur chaque ligne.

Le format est :

NAME1 VALUE1,NAME2 VALUE2,NAME3 VALUE3, etc

Supposons que j'écrive :

read l
IFS=","
set -A nvls $l
echo "$nvls[2]"

Cela me donnera la deuxième paire nom-valeur, gentiment et facilement. Maintenant, supposons que la tâche soit étendue pour que les valeurs puissent inclure des virgules. Elles doivent être échappées, comme ceci :

NAME1 VALUE1,NAME2 VALUE2_1\,VALUE2_2,NAME3 VALUE3, etc

Évidemment, mon code ne fonctionne plus, puisque "read" supprime tous les guillemets et le deuxième élément du tableau sera juste "NOM2 VALEUR2_1".

Je suis coincé avec un ancien ksh qui ne dispose pas de "read -A array". J'ai essayé plusieurs astuces avec "read -r" et "eval set -A ....", sans succès. Je ne peux pas utiliser "read nvl1 nvl2 nvl3" pour faire de l'unscaping et du splitting dans read, puisque je ne sais pas à l'avance combien de paires nom-valeur se trouvent dans chaque ligne.

Est-ce que quelqu'un a une astuce utile à me proposer ?

PS Je sais que j'ai déjà fait cela en Perl, Python et même en awk. Cependant, je dois le faire en ksh (... ou mourir en essayant ;)

1voto

ADEpt Points 4405

Comme cela arrive souvent, j'ai conçu une réponse quelques minutes après avoir posé la question sur un forum public :(

J'ai contourné le problème de citation/décitation en faisant passer le fichier d'entrée par le sed script suivant :

sed -e 's/\([^\]\),/\1\
/g;s/$/\
/

Il a converti l'entrée en :

NAME1.1 VALUE1.1
NAME1.2 VALUE1.2_1\,VALUE1.2_2
NAME1.3 VALUE1.3
<empty line>
NAME2.1 VALUE2.1
<second record continues>

Maintenant, je peux analyser cette entrée comme ceci :

while read name value ; do
  echo "$name => $value"
done

La valeur aura ses virgules non citées par "read", et je peux mettre "name" et "value" dans un tableau associatif, si je veux.

PS Puisque je ne peux pas accepter ma propre réponse, dois-je supprimer la question, ou ... ?

0voto

Bill Karwin Points 204877

Vous pouvez également modifier le \, en quelque chose d'autre qui n'apparaîtra dans aucune de vos chaînes de caractères, puis changez-le à nouveau après avoir divisé l'entrée en un tableau. Vous pouvez utiliser la syntaxe de substitution de motif intégrée à ksh pour faire cela, vous n'avez pas besoin d'utiliser sed ou awk ou autre.

read l
l=${l//\\,/!!}
IFS=","
set -A nvls $l
unset IFS
echo ${nvls[2]/!!/,}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X