Comment inverser l'ordre des lignes sélectionnées dans Vim?

95

Par exemple, si j'ai quatre lignes comme suit:

la première ligne
la deuxième ligne
la troisième ligne
la quatrième ligne

Je veux les inverser

la quatrième ligne
la troisième ligne
la deuxième ligne
la première ligne

Comment pourrais-je faire cela dans Vim?

Jichao
la source
1
:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1 vi.stackexchange.com/a/2107/10254
Qeatzy

Réponses:

87

Pour inverser toutes les lignes d'un fichier,

:g/^/m0

Pour une explication voir

:help 12.4

qui montre également comment inverser une plage de lignes.

Garyjohn
la source
12
Excellent conseil sur la section d'aide exacte! Pour résumer: 1. placez un marqueur sur la dernière ligne que vous souhaitez inverser (je nomme le marqueur 'a' en utilisant ma), 2. déplacez le curseur sur la première ligne du bloc, 3. tapez:'a,.g/^/m 'a
Brent Faust
70

Sélectionnez les lignes souhaitées, appuyez sur !, puis dans l'invite résultante, dirigez les lignes tacun à un :'<,'>!tac. Voir man tacpour plus de détails.

Rhys Ulerich
la source
4
Pour sélectionner les lignes, utilisez shift+vpour passer en mode ligne visuelle, puis jpour ajouter des lignes à la sélection.
Wisbucky
Je peux confirmer que cela fonctionne dans les fenêtres avec gvim, aussi bien! Sinon, vous devez utiliser des numéros de ligne absolus (vous pouvez peut-être utiliser un nombre relatif, mais vous devez être prudent) avec le :g/^/m0(ce qui est également très difficile à retenir) ... Donc, essentiellement, tac devrait être avec vim, quelle que soit la plateforme. vous êtes sur, MAIS ce n'est pas 100% vimscript, MAIS on s'en fiche: P
dylnmc
tac n'est pas une gestion entièrement native de vim, mais la commande 'm'ove prend un numéro de ligne et ce n'est pas toujours raisonnable. J'utilise souvent une marque dans le cadre d'une gamme, donc :.,'a!tacfonctionne avec un minimum d'effort.
studog
Après utilisation shift+v, vous pouvez utiliser }pour atteindre le paragraphe suivant ou vider un espace vertical. Aussi man tac: concatenate and print files in reverse.
nilon
33

Sur Mac OS X, tacn’existe pas, mais vous pouvez utiliser tail -rdans le même sens:

:%!tail -r

Cela fonctionne également bien pour le mode visuel:

:'<,'>!tail -r

Extrait de tail(1)la page de manuel de:

L'option -r entraîne l'affichage de l'entrée dans l'ordre inverse, ligne par ligne. De plus, cette option modifie la signification des options -b, -c et -n. Lorsque l'option -r est spécifiée, ces options spécifient le nombre d'octets, de lignes ou de blocs de 512 octets à afficher, au lieu des octets, des lignes ou des blocs du début ou de la fin de l'entrée à partir de laquelle commencer l'affichage. La valeur par défaut pour l'option -r consiste à afficher toutes les entrées.

Thomas Perl
la source
3
Excellent! Donc, pour fournir 'tac' sous OS X:alias tac='tail -r'
Brent Faust
4
Vous pouvez aussi brew install coreutilset utiliser gtac.
Andrew Marshall
1
Génie. Jamais pensé à utiliser! commandes pour ce type de manipulation de ligne visuelle.
Charlie Dalsass
3

Pour ceux qui sont plus à l'aise avec le mode visuel:
1. Identifiez le numéro de ligne au-dessus de la sélection que vous souhaitez inverser :set nu.
2. Shift-Vpour mettre en surbrillance la sélection que vous voulez inverser (mode visuel).
3 :g/^/m <Line number from step 1>..

Notez qu'en mode visuel, il apparaîtra automatiquement comme :'<,'>g/^/m <Line number>lorsque vous tapez la commande à partir de 3.

Cette commande consiste à déplacer la sélection ligne par ligne dans le numéro de ligne que vous lui avez attribué. Lorsque le deuxième élément est inséré dans le numéro de ligne indiqué, il passe au premier numéro de ligne + 1. Le troisième abaisse les premier et deuxième et ainsi de suite jusqu'à ce que toute la liste soit insérée dans le seul numéro de ligne, ce qui entraîne une liste ordonnée inverse.

Horta
la source
4
Vous pouvez utiliser le à la '<place du numéro de ligne manuellement. Il suffit de commencer la sélection une ligne plus tôt et de l'exécuter :'<,'>g/^/m'<.
Palec
3

Une commande :Rev[erse]et des mappages facultatifs pour votre vimrc, de sorte que vous n'avez pas à vous souvenir et à exécuter les étapes non évidentes de cette recette:

" Reverse the lines of the whole file or a visually highlighted block.
    " :Rev is a shorter prefix you can use.
    " Adapted from http://tech.groups.yahoo.com/group/vim/message/34305
command! -nargs=0 -bar -range=% Reverse
    \       let save_mark_t = getpos("'t")
    \<bar>      <line2>kt
    \<bar>      exe "<line1>,<line2>g/^/m't"
    \<bar>  call setpos("'t", save_mark_t)

nmap <Leader>r :Reverse<CR>
xmap <Leader>r :Reverse<CR>

( :xmapmappe pour le mode visuel mais pas pour la sélection, comme :help mapmode-xconseillé pour mapper les caractères imprimables.)

(Basé sur: http://tech.groups.yahoo.com/group/vim/message/34305 )

Aaron Thoma
la source
Cela devrait être la réponse acceptée OMI. Généralement utile et que je n'ai pas à retenir :'<,'>g/^/m'<:)
Eliot
1
@ Eliot, merci! :) (J'ai ajouté un peu de 'contenu bonus'.;))
Aaron Thoma
Comment puis-je dire début de sélection -1 dans ce cas? Parce que le déménagement commence à ce stade.
SergioAraujo
@SergioAraujo: Quelque chose comme :-1,+1Revce que vous cherchez? Sachez que vous pouvez visuellement sélectionner la plage que vous voulez inverser, par exemple: V7j:Rev. Si cela ne répond pas à votre question, je ne l'ai pas comprise. Vous devrez donc la développer ou la reformuler pour moi.
Aaron Thoma
1

Disons que vous êtes à la ligne 3, nous avons donc une plage de 3 à 6. Il suffit de taper.

:3,6g/^/m2
SergioAraujo
la source
1
Vous pouvez laisser le numéro de la ligne en cours implicite: avec le curseur sur la première ligne de votre plage, vous pouvez raccourcir à :,6g/^/m2; ou quand sur la dernière ligne de la gamme: :3,g/^/m2; et :3,6g/^/m2fonctionne à partir de n’importe où dans le fichier.
Aaron Thoma