@MaxMackie askubuntu.com/questions/88142/… . Je ne peux pas mettre la main sur un mod là à cette heure, alors je l'ai signalé en leur demandant de migrer s'ils le souhaitent; il a déjà une réponse acceptée, donc je ne sais pas s'ils le feront
Michael Mrozek
@MichaelMrozek, hmmm que se passe-t-il habituellement dans ces situations? Gardons-nous simplement les doublons?
n0pe
1
Sauf si vous devez exécuter sur un système qui ne dispose que d'outils de base, voir Existe
Gilles 'SO- arrête d'être méchant'
Réponses:
7
Outre la façon de couper et de réorganiser les champs (traités dans les autres réponses), il y a le problème des champs CSV originaux.
Si vos données entrent dans cette catégorie "décalée", un peu de pré et post filtrage peut s'en occuper. Les filtres ci - dessous ont besoin les caractères \x01, \x02, \x03, \x04apparaissent nulle part dans vos données.
Voici les filtres enroulés autour d'un simple awkvidage de champ.
Remarque: le champ-cinq a une disposition de "champ entre guillemets" invalide / incomplète, mais elle est bénigne à la fin d'une ligne (en fonction de l'analyseur CSV). Mais, bien entendu, cela entraînerait des résultats inattendus problématiques s'il était échangé de sa position de fin de ligne actuelle .
Mise à jour; user121196 a signalé un bogue lorsqu'une virgule précède une citation finale . Voici le correctif.
Les données
cat <<'EOF'>file
field one,"fie,ld,two",field"three","field,\",four","field,five
"15111 N. Hayden Rd., Ste 160,",""
EOF
field one
"fie,ld,two"
field"three""field,\",four""field,five
"15111 N. Hayden Rd., Ste 160,"""
Voici le pré filtre , développé avec des commentaires.
Le post-filtre n'est qu'un renversement de \x01. \x02, \x03,\x04
sed -r '
s/^/,/# add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/# when no trailing quote on last field :MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter'
comment supprimeriez-vous la nième colonne basée sur ce filtre?
user121196
@ user121196 - Comme mentionné dans sa première phrase, cette réponse montre un moyen de rendre les données CSV plus cohérentes. Par exemple. en remplaçant temporairement une virgule intégrée aux guillemets par un caractère de jeton neutre ... puis en la retournant dans une virgule après le déplacement / coupe / suppression. Encore une fois, comme mentionné, l'étape déplacer / couper / supprimer est remplacée par un simple vidage de champ awk .
Peter.O
1
il échoue pour ce cas: "15111 N. Hayden Rd., Ste 160,", ""
user121196
@ user121196: Merci de l'avoir signalé. J'ai mis à jour la réponse avec un correctif.
Peter.O
15
Cela dépend si votre fichier CSV utilise des virgules uniquement pour les délimiteurs, ou si vous avez une folie comme:
champ un, "champ, deux", champ trois
Cela suppose que vous utilisez un simple fichier CSV:
Supprimer une colonne
Vous pouvez vous débarrasser d'une seule colonne de plusieurs façons; J'ai utilisé la colonne 2 comme exemple. La façon la plus simple est probablement d'utiliser cut, qui vous permet de spécifier un délimiteur -det les champs que vous souhaitez imprimer -f; cela lui dit de se séparer par des virgules et le champ de sortie 1 et les champs 3 jusqu'à la fin:
$ cut -d,-f1,3-/path/to/your/file
Si vous avez réellement besoin d'utiliser sed, vous pouvez écrire une expression régulière qui correspond aux premiers n-1champs, au nchamp th et au reste, et ignorer la sortie du nth (ici n2, donc le premier groupe correspond à l' 1heure :) \{1\}:
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/'/path/to/your/file
Il existe plusieurs façons de le faire awk, aucune d'entre elles n'est particulièrement élégante. Vous pouvez utiliser une forboucle, mais gérer la virgule de fin est une douleur; en ignorant que ce serait quelque chose comme:
Dans sedc'est essentiellement la même expression que précédemment, mais vous capturez également la colonne cible et incluez ce groupe plusieurs fois dans le remplacement:
$ sed 's/\(\([^,]\+,\)\{1\}\)\([^,]\+,\)\(.*\)/\1\3\3\4/'/path/to/your/file
Dans awkle cas de la boucle for, ce serait quelque chose comme (en ignorant à nouveau la virgule de fin):
Puisque c'est CSV, vous aurez également besoin BEGIN { FS=","; OFS=","; }.
1
Je pense que même FS = OFS = "," fonctionnera.
5
Étant donné un fichier délimité par des espaces au format suivant:
12345
Vous pouvez supprimer le champ 2 avec awk comme ceci:
awk '{ sub($2,""); print}' file
qui revient
1345
Remplacez la colonne 2 par la colonne n, le cas échéant.
Pour dupliquer la colonne 2,
awk '{ col = $2 " " $2; $2 = col; print }' file
qui revient
122345
Pour commuter les colonnes 2 et 3,
awk '{temp = $2; $2 = $3; $3 = temp; print}'
qui revient
13245
awk est généralement très bon pour gérer le concept de champs . Si vous avez affaire à un fichier CSV et non à un fichier délimité par des espaces, vous pouvez simplement utiliser
awk -F,
pour définir votre champ comme une virgule, au lieu d'un espace (qui est la valeur par défaut). Il existe un certain nombre de bonnes ressources awk en ligne, dont une que je liste comme source ci-dessous.
Je ne sais pas grand-chose awk, mais il semble produire un espace séparé, même si le séparateur de champ est ,(le séparateur de champ contrôle simplement la façon dont il gère les entrées)
Michael Mrozek
@MichaelMrozek: oui, c'est la variable OFS awk qui contrôle le séparateur de champ de sortie.
enzotib
Oui, et comme je le mentionne dans ma réponse, vous pouvez passer l'option -F à awk pour changer le délimiteur (par exemple -F,)
Réponses:
Outre la façon de couper et de réorganiser les champs (traités dans les autres réponses), il y a le problème des champs CSV originaux.
Si vos données entrent dans cette catégorie "décalée", un peu de pré et post filtrage peut s'en occuper. Les filtres ci - dessous ont besoin les caractères
\x01
,\x02
,\x03
,\x04
apparaissent nulle part dans vos données.Voici les filtres enroulés autour d'un simple
awk
vidage de champ.Remarque: le champ-cinq a une disposition de "champ entre guillemets" invalide / incomplète, mais elle est bénigne à la fin d'une ligne (en fonction de l'analyseur CSV). Mais, bien entendu, cela entraînerait des résultats inattendus problématiques s'il était échangé de sa position de fin de ligne actuelle .
Mise à jour; user121196 a signalé un bogue lorsqu'une virgule précède une citation finale . Voici le correctif.
Les données
Le code
Le résultat:
Voici le pré filtre , développé avec des commentaires.
Le post-filtre n'est qu'un renversement de
\x01
.\x02
,\x03
,\x04
la source
Cela dépend si votre fichier CSV utilise des virgules uniquement pour les délimiteurs, ou si vous avez une folie comme:
Cela suppose que vous utilisez un simple fichier CSV:
Supprimer une colonne
Vous pouvez vous débarrasser d'une seule colonne de plusieurs façons; J'ai utilisé la colonne 2 comme exemple. La façon la plus simple est probablement d'utiliser
cut
, qui vous permet de spécifier un délimiteur-d
et les champs que vous souhaitez imprimer-f
; cela lui dit de se séparer par des virgules et le champ de sortie 1 et les champs 3 jusqu'à la fin:Si vous avez réellement besoin d'utiliser
sed
, vous pouvez écrire une expression régulière qui correspond aux premiersn-1
champs, aun
champ th et au reste, et ignorer la sortie dun
th (icin
2, donc le premier groupe correspond à l'1
heure :)\{1\}
:Il existe plusieurs façons de le faire
awk
, aucune d'entre elles n'est particulièrement élégante. Vous pouvez utiliser unefor
boucle, mais gérer la virgule de fin est une douleur; en ignorant que ce serait quelque chose comme:Je trouve plus facile de sortir le champ 1, puis
substr
de tout retirer après le champ 2:C'est ennuyeux pour les colonnes plus loin
Duplication d'une colonne
Dans
sed
c'est essentiellement la même expression que précédemment, mais vous capturez également la colonne cible et incluez ce groupe plusieurs fois dans le remplacement:Dans
awk
le cas de la boucle for, ce serait quelque chose comme (en ignorant à nouveau la virgule de fin):Le
substr
chemin:(tcdyl a trouvé une meilleure méthode dans sa réponse )
Déplacer une colonne
Je pense que la
sed
solution découle naturellement des autres, mais elle commence à devenir ridiculement longuela source
awk
est votre meilleur pari.awk
imprime les champs par numéro, donc ...Pour supprimer une colonne, pas l'imprimer:
Pour modifier la commande:
Redirigez vers un fichier de sortie.
awk
peut également formater la sortie.Sortie au format awk
la source
BEGIN { FS=","; OFS=","; }
.Étant donné un fichier délimité par des espaces au format suivant:
Vous pouvez supprimer le champ 2 avec awk comme ceci:
qui revient
Remplacez la colonne 2 par la colonne n, le cas échéant.
Pour dupliquer la colonne 2,
qui revient
Pour commuter les colonnes 2 et 3,
qui revient
awk est généralement très bon pour gérer le concept de champs . Si vous avez affaire à un fichier CSV et non à un fichier délimité par des espaces, vous pouvez simplement utiliser
pour définir votre champ comme une virgule, au lieu d'un espace (qui est la valeur par défaut). Il existe un certain nombre de bonnes ressources awk en ligne, dont une que je liste comme source ci-dessous.
Source pour # 3
la source
awk
, mais il semble produire un espace séparé, même si le séparateur de champ est,
(le séparateur de champ contrôle simplement la façon dont il gère les entrées)Cela fonctionnera pour la suppression
Contribution
Sortie
la source