Comment remplacer un personnage par une nouvelle ligne dans Vim


1967

J'essaie de remplacer chacun ,dans le fichier actuel par une nouvelle ligne:

:%s/,/\n/g 

Mais il insère ce qui ressemble à un ^@au lieu d'une nouvelle ligne réelle. Le fichier n'est pas en mode DOS ou quoi que ce soit.

Que devrais-je faire?

Si vous êtes curieux, comme moi, consultez la question Pourquoi est-ce que \ ra newline pour Vim? ainsi que.


2
Stack Overflow est un site de questions de programmation et de développement. Cette question semble être hors sujet car elle ne concerne pas la programmation ou le développement. Voir Quels sujets puis-je poser ici dans le centre d'aide. Peut-être que Super User ou Unix & Linux Stack Exchange seraient un meilleur endroit pour demander.
2018

5
@jww cette question a 10 ans ... semble trop vieille pour migrer. Il y a beaucoup de questions comme celle-ci, par exemple: stackoverflow.com/questions/10175812/…
Vinko Vrsalovic

14
@jww vim est un outil couramment utilisé par les programmeurs et les questions sur les outils couramment utilisés par les programmeurs sont abordées dans Stack Overflow . Bien évidemment, cela convient mieux à Vi et Vim .
user202729

Réponses:


2565

Utilisez \rau lieu de \n.

La substitution par \ninsère un caractère nul dans le texte. Pour obtenir une nouvelle ligne, utilisez \r. Cependant, lors de la recherche d'une nouvelle ligne, vous utiliseriez toujours \n. Cette asymétrie est due au fait que \net \r faire des choses légèrement différentes :

\ncorrespond à une fin de ligne (nouvelle ligne), alors qu'il \rcorrespond à un retour chariot. En revanche, dans les substitutions, \nun caractère nul est \rinséré tandis qu'un caractère de nouvelle ligne est inséré (plus précisément, il est traité comme l'entrée <CR>). Voici un petit exemple non interactif pour illustrer cela, en utilisant la fonction de ligne de commande Vim (en d'autres termes, vous pouvez copier et coller ce qui suit dans un terminal pour l'exécuter). xxdmontre un hexdump du fichier résultant.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

En d'autres termes, \na inséré l'octet 0x00 dans le texte; \ra inséré l'octet 0x0a.


127
/ r est traité comme une pression sur la touche Entrée / Retour. Il fonctionne sur toutes les plateformes.
Luka Marinko


14
Je souhaite que cela fonctionne pour le vi classique. Sur AIX v6.1, \rne fonctionne pas comme ça. Mais vous pouvez appuyer sur Ctrl-V Enterau lieu de taper \r, et cela fonctionne.
eksortso

3
Je suis en retard à la fête. Si \rinsère <CR>et \ninsère un null, comment pourrais-je remplacer quelque chose par un retour chariot?
M. Llama

2
@SunnyRaj êtes-vous sûr de l'histoire de CR et LF? J'avais l'impression qu'à l'origine, LF déplaçait le papier d'une rangée vers l'avant mais ne déplaçait pas la tête d'impression, et CR déplaçait la tête d'impression mais ne déplaçait pas le papier. Par conséquent, si votre système d'exploitation n'a pas converti l'entrée avant l'impression, vous ne pouvez pas simplement utiliser LF ou CR pour obtenir la sortie correcte. MS DOS a utilisé les données brutes de l'imprimante comme format de fichier texte, Mac OS a utilisé CR et converti à partir de cela au format brut de l'imprimante et UNIX a utilisé LF et converti à partir de cela au format brut de l'imprimante.
Mikko Rantalainen

210

Voici l'astuce:

Tout d'abord, définissez votre session Vi (m) pour autoriser la correspondance de motifs avec des caractères spéciaux (par exemple: nouvelle ligne). Cela vaut probablement la peine de mettre cette ligne dans votre fichier .vimrc ou .exrc:

:set magic

Ensuite, faites:

:s/,/,^M/g

Pour obtenir le ^Mpersonnage, tapez Ctrl+ Vet appuyez sur Enter. Sous Windows, faire Ctrl+ Q, Enter. La seule façon dont je peux m'en souvenir est de me souvenir du peu de sens qu'ils ont:

R: Quel serait le pire caractère de contrôle à utiliser pour représenter une nouvelle ligne?

B: Soit q(car cela signifie généralement «Quitter»), soit vparce qu'il serait si facile de taper Ctrl+ Cpar erreur et de tuer l'éditeur.

R: Faites en sorte.


9
J'utilise GVim sous Windows, et je n'ai besoin ni de :set magic(ce n'est pas dans mon ~ / _vimrc non plus) ou ctrl-q. Juste un simple ctrl-vsuivi d'une entrée crée le ^Mpersonnage pour moi très bien.
Chris Phillips

5
Cv ne représente pas une nouvelle ligne; c'est la commande "escape next literal character". Je ne sais pas non plus pour quoi Cv est un mnémonique, mais il y a une raison pour laquelle il ne correspond pas mentalement à la nouvelle ligne.
Jim Stewart

27
Ctrl-v est un mnémonique pour "verbatim" - c'est-à-dire échapper la touche suivante appuyée sur son code / caractère "verbatim". Dans Windows, c'est coller: pour garder les choses familières. Ctrl-Q est pour "(un) Devis" peut-être. Assez stupide, de toute façon - mais vous pouvez l'utiliser dans des fichiers binaires - par exemple pour rechercher Ctrl-A à travers Ctrl-Z (Ascii 1-26 je suppose).
Tomasz Gandor

1
Ctrl-Cne tue pas réellement l'éditeur, bien qu'il puisse vous annuler en mode normal. Ctrl-Vsignifie textuellement et Ctrl-Qsignifie que quelqu'un a fait l'erreur de charger le $VIMRUNTIME/mswin.vimfichier de configuration. Vous n'avez pas besoin de mswin. Utilisez simplement votre propre vimrc à la place.
00dani

wow ---- c'est incroyable. Je le faisais sed -n l jusqu'à présent. Bon à savoir que la même chose peut être obtenue avec Ctrl-vin vim.
arpit

98

Dans la syntaxe s/foo/bar, \ret \nont des significations différentes, selon le contexte.


Court:

Pour foo:

\ n = nouvelle ligne (LF sur Linux / Mac, CR + LF sur Windows)
\ r = retour chariot (CR)

Pour bar:

\ r = est une nouvelle ligne
\ n = octet nul.

Plus long (avec des nombres ASCII):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

Voici une liste des caractères de contrôle ASCII . Insérez-les dans Vim via Ctrl+ V, Ctrl+ ---key---.

Dans Bash ou les autres shells Unix / Linux, tapez simplement Ctrl+ ---key---.

Essayez Ctrl+ Mdans Bash. C'est la même chose que frapper Enter, car le shell réalise ce que l'on veut dire, même si les systèmes Linux utilisent des sauts de ligne pour délimiter les lignes.

Pour insérer des littéraux dans bash, les ajouter avec Ctrl+ Vfonctionnera également.

Essayez dans Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

Cela utilise des séquences d'échappement ANSI . Insérer les deux ^[« s via Ctrl+ V, Esc.

Vous pouvez également essayer Ctrl+ V, Ctrl+ M, Enterqui vous donnera ceci:

bash: $'\r': command not found

Rappelez-vous \rd'en haut? :>

Cette liste de caractères de contrôle ASCII est différente d'une table de symboles ASCII complète , en ce que les caractères de contrôle, qui sont insérés dans une console / pseudoterminal / Vim via la Ctrlclé (haha), peuvent y être trouvés.

Alors qu'en C et dans la plupart des autres langues, vous utilisez généralement les codes octaux pour représenter ces «caractères».

Si vous voulez vraiment savoir d'où tout cela vient: le TTY démystifié . C'est le meilleur lien que vous rencontrerez sur ce sujet, mais attention: il y a des dragons.


TL; DR

Habituellement foo= \n, et bar= \r.


1
Je suis donc intrigué par la façon dont vous substitueriez un caractère par un retour chariot
codeshot

2
@codeshot :s/x/^M/gdevrait faire l'affaire. Insérez le ^Mvia ctrl-vsuivi de ctrl-m.
sjas

3
Merci sjas, vous savez que cette question est l'une des plus étranges de tous les temps. 1008 votes pour la réponse qui ne dit rien de plus que "vim fait ce que vous avez trouvé. C'est parce que vim fait ce que vous avez trouvé. N'oubliez jamais que vim fait ce que vous avez trouvé." J'avais espéré trouver une liste restreinte de codes pour les personnages intéressants du motif, le remplacement et la raison de l'étrangeté afin qu'il soit facile de se souvenir et de prédire d'autres étranges similaires. Cela aurait obtenu mon vote.
codeshot

@codeshot une liste de caractères de contrôle ascii pourrait vous aider. Voir cs.tut.fi/~jkorpela/chars/c0.html pour plus de référence. Je mettrai à jour ma réponse pour inclure deux liens.
sjas

55

Vous devez utiliser:

:%s/,/^M/g

Pour obtenir le ^Mpersonnage, appuyez sur Ctrl+ vsuivi de Enter.


4
Je dois faire <Cv> <Cm> pour obtenir le caractère ^ M.
Jezen Thomas


24

Avec Vim sur Windows, utilisez Ctrl+ Qà la place de Ctrl+ V.


16

C'est la meilleure réponse pour la façon dont je pense, mais cela aurait été plus agréable dans un tableau:

Pourquoi \ ra newline pour Vim?

Donc, reformulation:

Vous devez utiliser \rpour utiliser un saut de ligne (ASCII 0x0A, la nouvelle ligne Unix) dans un remplacement regex, mais cela est particulier au remplacement - vous devez normalement continuer à vous attendre à utiliser \npour le saut de ligne et \rpour le retour chariot.

C'est parce que Vim utilisé \ndans un remplacement pour signifier le caractère NIL (ASCII 0x00). Vous pourriez vous attendre à ce que NIL l'ait été à la \0place, libérant \nson utilisation habituelle pour le saut de ligne, mais ayant \0déjà une signification dans les remplacements d'expressions régulières, il a donc été déplacé vers \n. Par conséquent, aller plus loin pour déplacer également la nouvelle ligne de \nà \r(qui dans un motif d'expression régulière est le caractère de retour chariot, ASCII 0x0D).

Caractère | Code ASCII | Représentation C | Match de regex | Remplacement des regex
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
néant | 0x00 | \ 0 | \ 0 | \ n
saut de ligne (nouvelle ligne Unix) | 0x0a | \ n | \ n | \ r
retour chariot | 0x0d | \ r | \ r | <inconnu>

NB: ^M( Ctrl+ V Ctrl+ Msous Linux) insère un retour à la ligne lorsqu'il est utilisé dans un remplacement regex plutôt qu'un retour chariot comme d'autres l'ont conseillé (je viens de l'essayer).

Notez également que Vim traduira le caractère de saut de ligne lors de l'enregistrement dans un fichier en fonction de ses paramètres de format de fichier et que cela pourrait prêter à confusion.


11

Depuis Eclipse , les ^Mpersonnages peuvent être intégrés dans une ligne et vous souhaitez les convertir en nouvelles lignes.

:s/\r/\r/g

8

Mais si l'on doit remplacer, alors la chose suivante fonctionne:

:%s/\n/\r\|\-\r/g

Dans ce qui précède, chaque ligne suivante est remplacée par la ligne suivante, puis |-une nouvelle ligne. Ceci est utilisé dans les tables wiki.

Si le texte est le suivant:

line1
line2
line3

Il est remplacé par

line1
|-
line2
|-
line3

7

Si vous devez le faire pour un fichier entier, il m'a également été suggéré d'essayer à partir de la ligne de commande:

sed 's/\\n/\n/g' file > newfile

1
Notez que cela nécessite GNU sed. Essayez printf 'foo\\nbar\n' | sed 's/\\n/\n/g'de voir si cela fonctionnera sur votre système. (Nous remercions les bonnes personnes de #bash sur freenode pour cette suggestion.)
Evan Donovan

Oui, mais la question concernait Vim. Il y a une question de débordement de pile Comment puis-je remplacer une nouvelle ligne (\ n) en utilisant sed? .
Peter Mortensen

5

Voici la réponse qui a fonctionné pour moi. De ce type:

---- citation Utilisez l'éditeur vi pour insérer un caractère de nouvelle ligne en remplacement


Quelque chose d'autre que je dois faire et dont je ne me souviens pas, puis je dois lever les yeux.

Dans vi, pour insérer un caractère de nouvelle ligne dans une recherche et remplacer, procédez comme suit:

:%s/look_for/replace_with^M/g

La commande ci-dessus remplacerait toutes les instances de «look_for» par «replace_with \ n» (avec \ n signifiant newline).

Pour obtenir le «^ M», entrez la combinaison de touches Ctrl+ V, puis appuyez sur la Entertouche (relâchez toutes les touches) .


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.