Comprendre les différences de référence de ligne via: g / ^ / norme et via:% norme

8

Disons que j'ai le fichier très simple suivant

a
b
c
d
e

et j'ai décidé que je veux ajouter des lignes vides après chaque ligne. Plusieurs méthodes différentes me viennent immédiatement à l'esprit. Nous pourrions simplement le faire (et donc embrasser l'échec). Nous pouvons enregistrer une macro comme qqo<ESC>jqet la répéter plusieurs fois.

Deux autres méthodes me semblaient plus évidentes à l'époque.

Tout d'abord, je pensais que j'émettrais la :normcommande osur chaque ligne. Alors je cours :%norm o. Mais ce qui se passe réellement, c'est que nous obtenons 5 lignes vides, suivies des lignes non séparées comme ci-dessus. J'interprète cela comme signifiant que par %norm, vim récupère réellement le message émis la commande normale suivante sur les cinq premières lignes de ce fichier de cinq lignes . La ocommande crée une nouvelle ligne et vim est "stupide" dans le sens où elle fait référence par numéro de ligne et non par un autre identifiant.

Eh bien, j'étais gêné. Sûr. J'ai essayé quelques autres choses pour voir si je pouvais faire fonctionner la méthode ci-dessus, mais hélas, je ne pouvais pas. Par curiosité, j'ai essayé mon autre méthode préférée d'application en masse. Cela m'a amené à essayer :g/^/norm o. À ma grande surprise, cela fonctionne très bien! Donc à mes yeux, il semble que vim ne soit pas "idiot" ici de la même manière que ci-dessus et référence les lignes par plus qu'un simple numéro de ligne.

Que se passe-t-il exactement?

davidlowryduda
la source
2
Sur une note de côté: vous pouvez aussi le faire comme ceci: :%s/$/\r/ou comme ceci: :%s/\n/\r\r/. La conclusion est que les nouvelles lignes peuvent être associées \n, mais doivent être écrites comme \rdes valeurs de remplacement.
lcd047

Réponses:

9

Eh bien, %c'est un raccourci pour 1,$(une plage allant de la première ligne à la dernière). De :he :%:

Line numbers may be specified with:             :range E14 {address}
        {number}        an absolute line number
        .               the current line                          :.
        $               the last line in the file                 :$
        %               equal to 1,$ (the entire file)            :%

Et pour :global:

The global commands work by first scanning through the [range] lines and
marking each line where a match occurs (for a multi-line pattern, only the
start of the match matters).
In a second scan the [cmd] is executed for each marked line with its line
number prepended.  For ":v" and ":g!" the command is executed for each not
marked line.  If a line is deleted its mark disappears.

Ainsi, le premier cas est comme parcourir une liste tout en la modifiant, donc un compteur sur des éléments de liste devient invalide. Dans le deuxième cas, nous marquons les éléments que nous voulons cibler en une seule passe, de sorte que même si la liste est modifiée lors de la deuxième passe, nous savons toujours sur quels éléments nous voulons travailler.

muru
la source
Ah, c'est même dans le fichier d'aide pour global. Comme je suis bête. Merci
davidlowryduda
homme - le g est exagérément fou utile. je dois passer plus de temps pour passer d'un utilisateur vi moyen à un utilisateur
expérimenté