reformater en vim pour une belle disposition des colonnes

126

J'ai cet ensemble de données dans un fichier csv

1.33570301776, 3.61194e-06, 7.24503e-06, -9.91572e-06, 1.25098e-05, 0.0102828, 0.010352, 0.0102677, 0.0103789, 0.00161604, 0.00167978, 0.00159998, 0.00182596, 0.0019804, 0.0133687, 0.010329, 0.00163437, 0.00191202, 0.0134425 
1.34538754675, 3.3689e-06, 9.86066e-06, -9.12075e-06, 1.18058e-05, 0.00334344, 0.00342207, 0.00332897, 0.00345504, 0.00165532, 0.00170412, 0.00164234, 0.00441903, 0.00459294, 0.00449357, 0.00339737, 0.00166596, 0.00451926, 0.00455153
1.34808186291, -1.99011e-06, 6.53026e-06, -1.18909e-05, 9.52337e-06, 0.00158065, 0.00166529, 0.0015657, 0.0017022, 0.000740644, 0.00078635, 0.000730052, 0.00219736, 0.00238191, 0.00212762, 0.00163783, 0.000750669, 0.00230171, 0.00217917

Comme vous pouvez le voir, les nombres sont formatés différemment et mal alignés. Y a-t-il un moyen dans vim d'aligner rapidement les colonnes correctement, de sorte que le résultat soit le suivant

1.33570301776,  3.61194e-06, 7.24503e-06, -9.91572e-06, 1.25098e-05, 0.0102828,  0.010352,   0.0102677,  0.0103789, 0.00161604, 0.00167978, 0.00159998, 0.00182596, 0.0019804,  0.0133687,  0.010329,   0.00163437, 0.00191202, 0.0134425 
1.34538754675,  3.3689e-06,  9.86066e-06, -9.12075e-06, 1.18058e-05, 0.00334344, 0.00342207, 0.00332897, 0.00345504,0.00165532, 0.00170412, 0.00164234, 0.00441903, 0.00459294, 0.00449357, 0.00339737, 0.00166596, 0.00451926, 0.00455153
1.34808186291, -1.99011e-06, 6.53026e-06, -1.18909e-05, 9.52337e-06, 0.00158065, 0.00166529, 0.0015657,  0.0017022, 0.000740644,0.00078635, 0.000730052,0.00219736, 0.00238191, 0.00212762, 0.00163783, 0.000750669,0.00230171, 0.00217917

Ce serait génial de copier et coller des sections avec ctrl-v. Des indices?

Stefano Borini
la source

Réponses:

263

Si vous utilisez une sorte d'UNIX (Linux, etc.), vous pouvez tricher et le filtrer via la commande column (1).

:%!column -t

Ce qui précède analysera les délimiteurs à l'intérieur des littéraux de chaîne, ce qui est faux, vous aurez donc probablement besoin d'étapes de pré-traitement et de spécifier le délimiteur pour ce fichier par exemple:

%!sed 's/","/\&/' | column -t -s '&'
ensoleillé256
la source
1
Commande cool, je n'en étais pas conscient (ayant écrit un script perl personnalisé pour faire ce genre d'opération dans le passé).
hlovdal
24
Parce que mes fichiers n'avaient pas d'espace que je devais utiliser :%!column -t -s ','. Il supprime les virgules, donc ce ne sont plus des fichiers csv techniques. Mais les arrange magnifiquement, c'est ce dont j'avais besoin.
Eduardo
27
Bon conseil! Juste en ajoutant, cela fonctionne aussi pour la sélection visuelle avec:'<,'>!column -t
freitass
2
Quelqu'un connaît-il une solution pour travailler avec des colonnes entre guillemets avec des virgules dans la colonne? exemple "2151 Main ST Houston, TX"
metrix
3
@metrix, voici une solution de contournement très maladroite: 1) convertir les espaces à l'intérieur des délimiteurs en un caractère différent, 2) puis exécuter columncomme décrit dans l'article, 3) puis remplacer vos délimiteurs en espaces. Un exemple de commande en mode visuel pour l'étape 1 est:'<,'>s/"\(\w\+\) \(\w\+\)"/"\1_\2"/g
Luciano
54

Parfois, nous voulons aligner seulement deux colonnes. Dans ce cas, nous n'avons besoin d'aucun plug-in et pouvons utiliser la fonctionnalité Vim pure comme ceci:

  1. Choisissez un séparateur. Dans le post d'OP, c'est une virgule, dans mon exemple c'est =.
  2. Ajoutez des espaces avant / après. J'utilise s/=/= ...spaces... /en sélection visuelle pour cela.
  3. Recherchez le mot le plus long et placez le curseur après lui.
  4. Supprimez tous les espaces blancs supplémentaires à l'aide d' dwun mouvement vertical.

Exemple de cette technique démontrée ci-dessous:

Exemple

Je n'ai pas besoin d'aligner les choses assez souvent pour installer un autre plugin, c'était donc ma façon préférée de l'accomplir - surtout que cela ne nécessite pas beaucoup de réflexion.

rr-
la source
4
Comment as-tu fait ce joli gif?
Stefano Borini
1
blog.bahraniapps.com/gifcam semble malheureusement être un outil uniquement Windows.
rr-
Lorsque vous avez terminé d'aligner la partie supérieure, comment avez-vous déplacé le curseur au milieu de l'écran, puis commencé à aligner la partie inférieure?
cychoi
5
Après, :s/=/ =/il est préférable d'utiliser Ctrl + Vpour sélectionner la colonne de droite, puis de l'aligner en utilisant <<et .pour répéter. Trouvé ici: stackoverflow.com/a/24704379/2152384
pozitron57
1
Ou créer une macro à faire de travail @ pozitron57
Arthur Julião
24

Comme le suggère sunny256, la columncommande est un excellent moyen de le faire sur les machines Unix / Linux, mais si vous voulez le faire en pur Vim (afin qu'il puisse également être utilisé sous Windows), le moyen le plus simple est d'installer Align plugin, puis faites:

:%Align ,
:%s/\(\s\+\),\s/,\1/g

La première ligne aligne les entrées sur les virgules et la seconde déplace la virgule afin qu'elle affleure la valeur précédente. Vous pourrez peut-être utiliser AlignCtrlpour définir un mappage personnalisé qui fait tout en une seule fois, mais je ne me souviens jamais comment l'utiliser ...

Éditer

Si cela ne vous dérange pas deux espaces entre les entrées et que vous souhaitez le faire en une seule commande, vous pouvez également faire:

:%Align ,\zs
DrAl
la source
Fonctionne parfaitement dans une table LaTeX::'<,'>Align &
Thomas
Cela peut également être accompli avec :%Align! lP0 \s( l= aligné à gauche, P0= 0 remplissage après le séparateur).
ntd
8

C'est une excellente réponse en utilisant les macros vim: https://stackoverflow.com/a/8363786/59384 - en gros, vous commencez à enregistrer une macro, formatez la première colonne, arrêtez l'enregistrement puis répétez la macro pour toutes les lignes restantes.

Copier / coller à partir de cette réponse:

qa0f:w100i <Esc>19|dwjq4@a

Notez le seul espace après le 100i, et le <Esc> signifie "appuyez sur échapper" - ne tapez pas "<Esc>" littéralement.

Traduction:

qa         -- record macro in hotkey a
0          -- go to beginning of line
f:         -- go to first : symbol
w          -- go to next non-space character after the symbol
100i <Esc> -- insert 100 spaces
19|        -- go to 19th column (value 19 figured out manually)
dw         -- delete spaces until : symbol
j          -- go to next line
q          -- stop recording macro
4@a        -- run the macro 4 times (for the remaining 4 lines)
zcrar70
la source
7

Nous avons maintenant aussi le fabuleux plugin EasyAlign , écrit par junegunn.

GIF de démonstration de son README:

rr-
la source
4

Vous pouvez utiliser le plugin csv.vim .

:%ArrangeColumn

Cependant, cela ne fera pas exactement ce que vous avez demandé: cela ajustera correctement le contenu des cellules, alors que vos valeurs seront alignées par la virgule décimale ou par le premier chiffre.

Le plugin a de nombreuses autres commandes utiles pour travailler avec des fichiers CSV.

Daan
la source
3

aussi si vous avez de très longues colonnes, il peut être pratique de désactiver le wrapping par défaut

: définir nowrap
:%! colonne -t

(notez que dans Debian, vous avez également une autre option pour la colonne -n ​​qui si vous voulez diviser plusieurs délimiteurs adjacents)

Amos Folarin
la source
beaucoup mieux avec nowrap. J'ai inclus votre suggestion, merci 'commande CSV set nowrap | %! colonne -t -s ',' '.
Peruz le
notez également l'option -n pour désactiver la fusion des colonnes vides. stackoverflow.com/questions/1875305/command-line-csv-viewer
Peruz
3

Je viens d'écrire tablign à cet effet. Installer avec

pip3 install tablign --user

Ensuite, marquez simplement la table dans vim et faites

:'<,'>:!tablign

entrez la description de l'image ici

Nico Schlömer
la source
1

Question assez ancienne, mais je me suis récemment servi d'un excellent plugin vim qui permet le formatage de table à la volée ou après le fait (selon votre cas d'utilisation):

https://github.com/dhruvasagar/vim-table-mode

Alice
la source
1

Voici une réponse de script Vim pure, pas de plugins, pas de macros:

Il serait peut-être plus clair de commencer par la solution de mon problème comme exemple. J'ai sélectionné les lignes de code que je voulais affecter, puis j'ai utilisé la commande suivante (rappelez-vous que le passage en mode commande à partir du mode visuel ajoute automatiquement le préfixe «'<,'>», donc cela agit sur la plage visuelle):

:'<,'>g``normal / "value<0d>D70|P`

Sauf que je n'ai PAS réellement tapé «<0d>». Vous pouvez saisir des caractères non imprimables sur la ligne de commande en appuyant sur ctrl-v, puis sur la touche que vous souhaitez saisir. «<0d>» est ce qui est rendu sur la ligne de commande après avoir tapé «ctrl-v enter». Ici, il est analysé par la commande «normal» comme sortie du mode de recherche «/». Le curseur passe alors à «valeur» dans la ligne courante.

Ensuite, nous supprimons simplement le reste de la ligne, passons à la colonne 70 (ou ce dont vous avez besoin dans votre cas), et [P] ut ce que nous venons de supprimer. Cela signifie que nous devons déterminer la largeur de la ligne la plus large, jusqu'à notre recherche. Si vous n'avez pas mis ces informations dans votre ligne d'état, vous pouvez voir la colonne du curseur en entrant la commande de mode normal 'g ctrl-g'. Notez également que passer à une colonne qui n'existe pas nécessite le paramètre «virtualedit»!

J'ai laissé le terme de recherche pour la commande: g (lobal) vide, car nous avons utilisé un bloc visuel et voulions affecter chaque ligne, mais vous pouvez le laisser en utilisant une sélection visuelle (et le «'<,'>») et mettre un terme de recherche à la place. Ou combinez une sélection visuelle et un terme de recherche pour affiner les choses plus finement / facilement.

Voici quelque chose que j'ai appris récemment: si vous vous trompez sur une commande de mode de commande complexe, annulez avec 'u' (si cela a affecté le tampon), puis appuyez sur «q:» pour entrer dans un tampon d'historique de commande spécial qui agit un peu comme un tampon conventionnel . Modifiez n'importe quelle ligne et appuyez sur Entrée, et la commande modifiée est entrée en tant que nouvelle commande. Indispensable si vous ne voulez pas avoir à vous soucier de tout formuler parfaitement du premier coup.

Atimholt
la source
0

J'ai écrit un script python qui permet aux utilisateurs de regrouper fondamentalement tout type de texte également en dehors de vim. Je ne sais pas si cela fonctionnera pour les utilisateurs Windows ou Mac.

columnice.py l'essentiel

Utilisation dans vim.

:'<,'>!columnice =

Cela utilisera le signe égal comme délimiteur. Le délimiteur n'est cependant pas jeté.

Bassim Huis
la source
0

J'ai ceci dans mon .vimrc.

command! CSV set nowrap | %s/,/,|/g | %!column -n -t -s "|" 

Cela aligne les colonnes tout en conservant la virgule, ce qui peut être nécessaire plus tard pour une lecture correcte. Par exemple, avec Python Pandas read_csv(..., skipinitialspace=True), merci les gars de Pandas pour cette option intelligente, sinon dans vim %s/,\s\+/,/g. Cela peut être plus facile si vous avez columnl'option --output-separator je suppose, mon ne le fait pas et je ne sais pas pourquoi (ma page de manuel pour la colonne indique 2004, sur ubuntu 18.04, je ne suis pas sûr que ubuntu obtiendra une nouvelle version) . Quoi qu'il en soit, cela fonctionne pour moi, et commentez si vous avez des suggestions.

Peruz
la source