web-dev-qa-db-fra.com

Comment puis-je convertir des espaces en onglets dans Vim ou Linux?

J'ai parcouru plusieurs questions sur Stack Overflow pour savoir comment convertir des espaces en tabulations sans trouver ce dont j'avais besoin. Il semble y avoir plus de questions sur la façon de convertir des tabulations en espaces, mais j'essaie de faire le contraire.

Dans Vim j'ai essayé :retab et :retab! sans chance, mais je pense que ceux-ci sont en fait pour aller de tabulations à des espaces de toute façon.

J'ai essayé à la fois expand et unexpand à l'invite de commande sans aucune chance.

Voici le fichier en question:

- http://gdata-python-client.googlecode.com/hg-history/a9ed9edefd61a0ba0e18c43e448472051821003a/samples/docs/docs_v3_example.py

Comment puis-je convertir des espaces Leading en onglets à l'aide de Vim ou du shell?

156
cwd

En utilisant Vim pour élargir tous les espaces (plus larges que 'tabstop' ), vous aviez raison d'utiliser retab mais assurez-vous d'abord que 'expandtab' est réinitialisé (:verbose set ts? et? est ton ami). retab prend une plage, donc je spécifie généralement % pour signifier "le fichier entier".

:set tabstop=2      " To match the sample file
:set noexpandtab    " Use tabs, not spaces
:%retab!            " Retabulate the whole file

Avant de faire quoi que ce soit du genre (en particulier avec les fichiers Python!), Je règle généralement 'list' , afin de pouvoir voir les espaces et les modifier. 

J'ai le mappage suivant dans mon .vimrc pour cela:

nnoremap    <F2> :<C-U>setlocal lcs=tab:>-,trail:-,eol:$ list! list? <CR>
261
Johnsyweb

1 - Si vous avez des espaces et voulez des onglets.

Tout d'abord, vous devez décider combien d'espaces auront un seul onglet. Cela dit, supposons que vous ayez des lignes avec 4 espaces de début, ou 8 ... Alors vous réalisez que vous voulez probablement une tabulation de 4 espaces. Maintenant, avec cette information, vous faites:

:set ts=4
:set noet
:%retab!

Il y a un problème ici! Cette séquence de commandes cherchera tout votre texte, pas seulement les espaces au début de la ligne. Cela signifie qu'une chaîne telle que: "Hey,␣this␣␣␣␣is␣4␣spaces" deviendra "Hey,␣this⇥is␣4␣spaces", mais ce n'est pas le cas! c'est un onglet!.

Pour résoudre ce petit problème, je recommande une search, au lieu de retab.

:%s/^\(^I*\)␣␣␣␣/\1^I/g

Cette recherche recherchera dans tout le fichier toutes les lignes commençant par un nombre quelconque d’onglets, suivi de 4 espaces, et le substituera au nombre d’onglets qu’il aura trouvé plus un.

Ceci, malheureusement, ne fonctionnera pas à la fois!

Au début, le fichier aura des lignes commençant par des espaces. La recherche ne convertira alors que les 4 premiers espaces en un onglet, et laissera ce qui suit ...

Vous devez répéter la commande. Combien de fois? Jusqu'à ce que vous obteniez un pattern not found. Je ne peux pas encore trouver un moyen d'automatiser le processus. Mais si vous le faites:

`10@:`

Vous avez probablement terminé. Cette commande répète la dernière recherche/remplacement 10 fois. Il est peu probable que votre programme comporte autant de retraits. Si c'est le cas, il suffit de répéter à nouveau @@.

Maintenant, juste pour compléter la réponse. Je sais que vous avez demandé le contraire, mais vous ne savez jamais quand il faut défaire les choses.

2 - Vous avez des onglets et voulez des espaces.

Tout d’abord, déterminez le nombre d’espaces dans lesquels vous souhaitez convertir vos onglets. Disons que vous voulez que chaque onglet soit 2 espaces. Vous faites alors:

:set ts=2
:set et
:%retab!

Cela aurait le même problème avec les chaînes. Mais en tant que meilleur style de programmation pour ne pas utiliser d'onglets durs dans les chaînes, vous faites réellement une bonne chose ici. Si vous avez vraiment besoin d'un onglet dans une chaîne, utilisez \t.

28
Dr Beco
:%s/\(^\s*\)\@<=    /\t/g

Traduction: Recherchez chaque instance de 4 espaces consécutifs (après le caractère =), mais uniquement si la ligne entière jusqu’à ce point est un espace (ceci utilise l’assertion de largeur nulle, \@<=). Remplacez chaque instance trouvée par un caractère de tabulation.

11
Simon Zuckerbraun

Modifie tous les espaces en tabulation:%S/\s/\t/g

3
murat budak

Si vous avez GNU coreutils installé, considérez %!unexpand --first-only ou pour les onglets à 4 espaces, considérez %!unexpand -t 4 --first-only (--first-only est présent au cas où vous invoqueriez accidentellement unexpand avec --all).

Notez que cela ne remplacera que les espaces précédant les tabulations prescrites, pas les espaces qui les suivent; vous ne verrez aucune différence visuelle dans vim sauf si vous affichez les onglets de manière plus littérale; Par exemple, mon ~/.vimrc contient set list listchars=tab:▸┈ (je suppose que c'est pourquoi vous pensiez que unexpand ne fonctionnait pas).

0
Adam Katz

Extrait Bash pour remplacer 4 - espaces (il y a deux {4} dans le script) par des onglets dans tous les fichiers .py du dossier ./app (de manière récursive):

find ./app -iname '*.py' -type f \
    -exec awk -i inplace \
    '{ match($0, /^(( {4})*)(.*?)$/, arr); gsub(/ {4}/, "\t", arr[1]) }; { print arr[1] arr[3] }' {} \; 

Ne modifie pas 4 espaces au milieu ou à la fin.

A été testé sous Ubuntu 16.0x et Linux Mint 18

0
maxkoryukov

Dans mon cas, j'avais plusieurs espaces (les champs étaient séparés par un ou plusieurs espaces) que je voulais remplacer par une tabulation. Ce qui suit l'a fait: 

:% s/\s\+/\t/g
0
zee