Comment puis-je exécuter: remplacer sur une partie seulement de la ligne et pas sur toute la ligne?

15

J'ai une ligne comme celle-ci:

function my_function(argument, another argument, but there are spaces)

Je veux remplacer les caractères d'espace (à l'intérieur des noms de l'argument) par un trait de soulignement. Je voudrais donc utiliser:

:s/\ /_/g

mais comment puis-je choisir de ne pas l'appliquer à toute la ligne, mais à partir, disons, de la position du curseur? (Ou le troisième mot)?

Feffe
la source
4
Dans une expression régulière, pour décrire la position actuelle du curseur, vous pouvez utiliser l'atome \%#. Ainsi, vous pouvez utiliser: :s/\v(%#.*)@<= /_/g. Ce qui pourrait être décrit comme un espace précédé de ( @<=) caractères après la position du curseur.
user9433424
1
Vous et Statox avez tous deux proposé l' \%#astuce, j'accepterai sa réponse si vous n'en écrivez pas une ... Mais l'un ou l'autre d'entre vous pourrait-il expliquer le regexp avec un peu plus explicitement?
Feffe

Réponses:

15

Vous pouvez utiliser la solution suivante:

Utilisez d'abord v$pour sélectionner le texte du curseur jusqu'à la fin de la ligne. Utilisez ensuite la commande suivante:

:s/\%V\ /_/g

Pour \%Vindiquer de modifier le texte dans la zone précédemment sélectionnée visuellement, voir :h /\%V.

Si je prends votre exemple:

function my_function(argument, another argument, but there are spaces)

Si mon curseur se trouve sur la 40e colonne et que j'utilise la commande que je viens d'écrire, j'obtiens:

function my_function(argument, another argument,_but_there_are_spaces)

En réponse à votre commentaire, vous pouvez également utiliser

  • \%# qui correspond à la position du curseur
  • \%>23c qui correspond après la 23e colonne.
  • \%>'m qui correspond après la position d'une marque

Voir :h /\%#, :h /\%>cet :h /\%>'m.

@ User9433424 a donné un moyen d'utiliser \%#dans son commentaire. Pour le motif avec la marque, vous pouvez le définir avec ma, puis utiliser:

:s/\%>'a /_/g

Une explication du modèle donné par @ User9433424 est la suivante:

:s/\v(%#.*)@<= /_/
:s/                    substitution command
   \v                  Enable the very magic mode
      %#.*             Any characters from the cursor position
           @<=         Check for matches just before what follows
              space    Followed by a space
               /_/     Substitute the matches by underscores

Vous aurez envie de voir :h \vet:h /\@<=

statox
la source
Ça fonctionne bien ! Mais je ne suis pas vraiment habitué aux sélections visuelles et l'ensemble du processus semble un peu "lourd" ... Pensez-vous qu'il pourrait y avoir quelque chose de plus rapide?
Feffe
Oui, permettez-moi de mettre à jour ma réponse :)
statox
User9433424 a donné cet indice juste avant vous, mais vous avez répondu, donc je vais accepter votre réponse si cela vous convient - pourriez-vous peut-être expliquer le modèle d'expression rationnelle qu'il utilise un peu plus? Je suis toujours aux prises avec ça ...
Feffe
J'ai essayé de rendre la réponse aussi claire que possible mais si @ User9433424 écrit sa propre réponse, n'hésitez pas à l'accepter.
statox
1
Très belle explication de l'expression rationnelle, merci! Et merci pour votre commentaire sur la réponse à laquelle accepter :)
Feffe
5

Vous pouvez utiliser look behind ( :h \@<=) pour vous assurer qu'il y a un «(» précédent et une limite de fin de mot ( :h \>) pour vous assurer que la substitution se produit où vous le souhaitez.

Donc, avec le texte:

function my_function(argument, another argument, but there are spaces)

exécution de la commande:

:s/\((.*\)\@<=\> /_/g

produira:

function my_function(argument, another_argument, but_there_are_spaces)

Cela pourrait être plus facile que de devoir positionner le curseur à chaque fois, à condition que la substitution ait toujours un point de départ connu.

Antony
la source
2
La substitution n'a pas toujours un point de départ connu: c'était uniquement pour ... corriger une étrange série de faute de frappe que j'ai faite. Mais votre réponse est néanmoins intéressante, merci!
Feffe