Sed à diviser en fonction de la gestion des guillemets entre guillemets et des données sans virgule dans plusieurs guillemets

J’ai des données comme ci-dessous

123,"john,test",John"test,""john"",345 

Le ci-dessus doit être divisé comme ci-dessous,

 123 "john,test" John"test ""john"" 345 

J’ai essayé d’utiliser sed pour gérer les virgules entre guillemets lors de la division, mais pour les données qui se trouvent entre plusieurs guillemets doubles ne s’affiche pas correctement. De plus, les données entre guillemets doubles ne sont pas traitées. J’ai essayé d’utiliser awk mais je ne pouvais pas utiliser la fonctionnalité fpat car nous avons une version plus ancienne de awk.

Pouvez-vous aider avec la solution pour le même?

Cela pourrait fonctionner pour vous (GNU sed):

 sed -r 's/([^",]*("[^"]*"[^",]*)*),/\1\n/g' file 

Remplacez toutes les virgules non entourées par des guillemets avec des nouvelles lignes.

Plus en profondeur: Groupez zéro ou plusieurs caractères qui ne contiennent pas de guillemets ou de guillemets doubles, suivis de zéro ou plusieurs groupes de guillemets doubles suivis de zéro ou plusieurs caractères sans guillemets (peuvent être des virgules), suivis d’un double guillemet suivi de zéro ou plusieurs caractères qui ne contiennent pas de guillemets doubles, suivis d’une virgule, et remplacent la virgule finale par une nouvelle ligne. Faites cela globalement dans tout le fichier.

Maintenant, si les guillemets et les guillemets sont cités …

sed est pour de simples substitutions sur des lignes individuelles, c’est tout. Pour toute autre chose comme votre problème, vous devriez utiliser awk. Voir Quel est le moyen le plus efficace d’parsingr efficacement le format CSV avec awk? Pour savoir comment gérer CSV avec n’importe quel awk, même si les champs contiennent des nouvelles lignes mais avec votre problème spécifique – vous avez dit que vous ne pouviez pas utiliser FPAT mais que FPAT est juste un raccourci GNU (match ()) si vous ne pouvez pas faire ceci:

 $ awk -v FPAT='[^,]+|"[^"]+"' '{for (i=1; i<=NF;i++) print i, "<" $i ">"}' file 1 <123> 2 <"john,test"> 3  4 <""john""> 5 <345> 

alors faites ceci à la place:

 $ awk '{ while ( match($0,/[^,]+|"[^"]+"/) ) { print ++i, "<" substr($0,RSTART,RLENGTH) ">"; $0=substr($0,RSTART+RLENGTH) } }' file 1 <123> 2 <"john,test"> 3  4 <""john""> 5 <345>