J'ai un TSV avec des champs qui ressemblent à:
name, location,1 2 3 4 5,
Quand j'utilise sed 's / \ w /, / g'
Je me retrouve avec un csv où 1, 2, 3, 4 et 5 sont considérés comme des entrées séparées.
Je voudrais que ce soit '1 2 3 4 5'
J'ai essayé de convertir des virgules en espace blanc avant d'exécuter la commande ci-dessus en utilisant
sed 's/,/\w/g'
mais lors de la conversion de l'espace blanc en virgules, il inclut des espaces blancs simples ainsi que les tabulations, donc qu'est-ce que l'expression régulière pour un seul caractère d'espacement?
Sortie souhaitée:
name location 1,2,3,4,5
4 Réponses :
Comme mentionné dans un commentaire, CSV traite généralement les occurrences de son caractère séparateur dans les valeurs en mettant la valeur entre guillemets, donc je vous suggère simplement de traiter cela en mettant chaque valeur entre guillemets:
sed -E 's/"/\\"/g;s/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'
Vous pouvez l'essayer ici .
Cela laisse une virgule comme dans votre exemple sortie, si vous voulez l'éviter, vous pouvez utiliser ce qui suit:
s/\t+$//
Si vos données d'origine contiennent "
, vous devrez cependant les échapper, que vous pouvez réaliser en ajoutant la substitution suivante avant les autres:
s/"/\\"/g
Comme Ed Morton suggère que nous puissions également supprimer les champs vides de fin:
sed -E 's/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'
En conclusion, j'utiliserais ce qui suit:
sed -E 's/([^\t]*)(\t|$)/"\1",/g'
@EdMorton, la virgule de fin était dans l'exemple de sortie d'OP et ma réponse le mentionne et propose une alternative. J'ai cependant résolu les deux autres problèmes.
Wow, je n'ai même pas remarqué que l'OP voulait changer toutes ses virgules en blancs dans ce dernier champ non plus! Ce que vous avez maintenant est meilleur, mais cela supprimerait tout champ vide à la fin d'une ligne.
Je viens de voter et j'ai remarqué que le CSV résultant cassait jquery-csv. Après de nombreuses recherches, j'ai découvert que vous deviez échapper aux guillemets doubles avec un autre guillemet double ! La commande résultante serait donc sed -E 's / "/" "/ g; s / \ t + $ //; s / ^ /" /; s / \ t / "," / g; s / $ / "/ '
, qui a bien fonctionné pour mes besoins.
Remplacez les tabulations par ","
et placez les lignes entre guillemets ou remplacez les virgules par des espaces et les tabulations par des virgules. Dans les deux cas, vous obtiendrez un fichier CSV valide.
$ cat file name location 1,2,3,4,5 $ $ sed 's/\t/","/g; s/^\|$/"/g' file "name","location","1,2,3,4,5" $ $ sed 's/,/ /g; s/\t/,/g' file name,location,1 2 3 4 5
Et dans awk:
$ awk -v OFS="," '{ # output delimiter to a comma * for(i=1;i<=NF;i++) # loop all fields if($i~/,/) # if comma in field $i="\"" $i "\"" # surround with quotes ** $1=$1 # rebuild record }1' file # output
Expliqué:
$ awk -v OFS="," '{for(i=1;i<=NF;i++)if($i~/,/)$i="\"" $i "\"";$1=$1}1' file name,location,"1,2,3,4,5"
* s'il y a de l'espace dans l'enregistrement, considérez le séparateur de champ de saisie en un tab avec awk -F "\ t"
.
** également, s'il y a des guillemets dans les champs avec des virgules, ils devraient peut-être être dupliqués ou échappés.
En fonction de vos besoins réels:
$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) $i="\""$i"\""} 1' file "name","location","1,2,3,4,5" $ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $1=$1} 1' file name,location,1 2 3 4 5 $ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $(NF+1)=""} 1' file name,location,1 2 3 4 5, $ echo 'a"b' | awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) { gsub(/"/,"\"\"",$i); $i="\""$i"\"" } } 1' "a""b"
Êtes-vous sûr que le fichier d'entrée est séparé par des tabulations ou s'agit-il simplement d'un groupe d'espaces?
Dans mon éditeur de texte (texte sublime), ils ressemblent à des onglets
les séparateurs dans les valeurs CSV sont généralement gérés en plaçant les valeurs entre guillemets, par exemple
nom, emplacement, "1,2,3,4,5"
. Estimeriez-vous une telle solution acceptable?Ouais ce serait super