J'ai 1 fichier csv avec 16 colonnes qui ressemble à ceci:
EB QUEST |Maria Valencia Loza |Consultor de ventas | Mexico |DF | 55457110 | 55450327 | 4003071 | evalencia@webquest.com.mx | 05/10/1999 | 0 |0 |0
J'ai essayé de fusionner 3 colonnes avec awk et sed mais pour une raison quelconque, je n'obtiens toujours pas le désir sortie:
WEB QUEST|Lazaro Martinez 0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
quand j'ai essayé awk -F "|" '{print $ 1, "|" $ 2, $ 3, $ 4, "|" $ 5 ...}'
pour une raison quelconque, des espaces sont ajoutés dans chaque | et voici le résultat que j'obtiens
WEB QUEST|Lazaro|Martinez|0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
des idées?
6 Réponses :
Bien que vos exigences ne soient pas claires, mais en voyant votre exemple de sortie attendu, j'ai appris que vous ne vouliez pas d'espace dans la sortie attendue si tel est le cas, vous devez définir OFS
comme | comme suit. Écrit et testé avec GNU awk
.
awk ' BEGIN{ s1=" " FS=OFS="|" re="(.*)\\|\\|\\|(.*)" } prev{ print gensub(re,"\\1|\\2","1",$0) } { $2=$2 s1 $3 s1 $4 $3=$4="" prev=$0 } END{ if(prev){ print gensub(re,"\\1|\\2","1",$0) } } ' Input_file
Vous pouvez joindre les colonnes 2,3 et 4 comme ceci, mais cela vous laissera avec les colonnes 3 et 4 vides:
awk -F\| -v OFS='|' '{$2=$2" "$3" "$4;$3=$4="";gsub(/[|]+/,FS)}1' file WEB QUEST|Lazaro Martinez 0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
Cela peut être résolu en imprimant les seuls premiers champs fixes, et la boucle à travers le reste.
awk -F\| '{a=$2" "$3" "$4;$3=$4="";printf "%s"FS"%s",$1,a;for (i=5;i<=NF;i++) printf FS"%s",$i}' file WEB QUEST|Lazaro Martinez 0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
Vous pouvez supprimer une colonne vide comme ceci, mais s'il y a une colonne vide dans l'original, elles ont disparu aussi:
awk -F\| -v OFS='|' '{$2=$2" "$3" "$4;$3=$4="";print $0}' file WEB QUEST|Lazaro Martinez 0|||Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
Vous avez dit avoir essayé avec awk
et sed
; cependant vous n'êtes pas lié à ceux-ci, vous pouvez utiliser read
.
Example:
#!/bin/bash while IFS="|" read -r foo var1 var2 var3 bar; do printf "%s|%s %s %s|%s\n" "${foo}" "${var1}" "${var2}" "${var3}" "${bar}" done <file.csv
Input:
WEB QUEST|Lazaro Martinez 0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
Ouptut:
WEB QUEST|Lazaro|Martinez|0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
NB La partie exécutable est juste là en tant que "meilleure pratique", vous pouvez obtenir le même résultat sans elle
E.G.
#!/bin/bash exec 3<file.csv while IFS="|" read -r foo var1 var2 var3 bar <&3; do printf "%s|%s %s %s|%s\n" "${foo}" "${var1}" "${var2}" "${var3}" "${bar}" done exec 3>&-
en lecture
est pathologiquement lent dans Bash. Vous voulez vraiment préférer un outil approprié comme sed
ou Awk.
La virgule dans Awk print
ajoute un séparateur de champ OFS
. Pour concaténer simplement les chaînes, omettez les virgules.
awk -F "|" '{print $1 "|" $2 $3 $4 "|" $5...}'
Une meilleure approche est probablement de définir OFS = "|"
et de simplement déplacer les troisième et quatrième champs, comme expliqué dans Existe-t-il un moyen de supprimer complètement les champs dans awk afin que les délimiteurs supplémentaires ne s'impriment pas?
Avec bash et GNU sed:
-e's/|/ /2' -e's/|/ /2'
Explication:
-e's/|/ /2'{,}
se développe en
sed -e's/|/ /2'{,} file
(voir accolade expansion ); il remplace donc le deuxième tube par un espace deux fois , donc les 2ème, 3ème et 4ème champs seront fusionnés.
sed
avec les quatre premiers champs correspondants:
WEB QUEST|Lazaro Martinez 0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0
affichera:
sed 's/\([^|]*\)|\([^|]*\)|\([^|]*\)|\([^|]*\)/\1|\2 \3 \4/' <<<"WEB QUEST|Lazaro|Martinez|0|Consultor de ventas|Mexico|DF|55457110|55450327|53445299|0|05/10/1999|0|0|0"
Quels sont vos résultats souhaités? "," peut ne pas être nécessaire.