Si j'ai le texte suivant:
foo
bar
Je le sélectionne visuellement et le copie.
Le texte est maintenant stocké dans le registre sans nom "
et voici son contenu (sortie de :reg "
):
"" foo^Jbar^J
Selon ce graphique , il semble que ce ^J
soit la notation caret pour un saut de ligne.
Si je veux dupliquer le registre sans nom dans le a
registre en tapant: :let @a = @"
Voici son contenu (sortie de :reg a
):
"a foo^Jbar^J
Cela n'a pas changé.
Si je le copie maintenant dans le registre de recherche en tapant :let @/ = @"
, voici son contenu (sortie de :reg /
):
"/ foo^@bar^@
Selon le tableau précédent, il semble que ce ^@
soit la notation caret pour un caractère nul.
Pourquoi un saut de ligne est-il automatiquement converti en caractère nul dans le registre de recherche (mais pas dans le a
registre)?
Si j'insère le registre sans nom sur la ligne de commande (ou dans une recherche après /
), en tapant :<C-R>"
, voici ce qui est inséré:
:foo^Mbar^M
Encore une fois, selon le dernier tableau, ^M
semble être la notation caret pour un retour chariot.
Pourquoi un saut de ligne est-il automatiquement converti en retour chariot sur la ligne de commande?
Modifier :
Habituellement, vous pouvez insérer un caractère de contrôle littéral en tapant:
<C-V><C-{character in caret notation}>
Par exemple, vous pouvez insérer un littéral <C-R>
en tapant <C-V><C-R>
.
Vous pouvez le faire pour apparemment n'importe quel personnage de contrôle.
Cependant, j'ai remarqué que je ne peux pas insérer un LF littéral dans un tampon ou sur la ligne de commande, car si je tape: <C-V><C-J>
il insère ^@
, un caractère nul, au lieu de ^J
.
Est-ce pour la même raison qu'un LF est converti en NUL dans le registre de recherche?
Modifier 2 :
Dans :h key-notation
, nous pouvons lire ceci:
<Nul> zero CTRL-@ 0 (stored as 10) <Nul>
<NL> linefeed CTRL-J 10 (used for <Nul>)
La stored as 10
partie sur la première ligne et used for <Nul>
sur la deuxième ligne pourrait indiquer qu'il y a une sorte de chevauchement entre un LF et un NUL, et qu'ils pourraient être interprétés comme la même chose. Mais ils ne peuvent pas être la même chose, car après avoir exécuté la commande précédente :let @/ = @"
, si je tape n
en mode normal pour arriver à la prochaine occurrence des 2 lignes foo
et bar
, au lieu d'obtenir une correspondance positive, j'ai le message d'erreur suivant:
E486: Pattern not found: foo^@bar^@
En outre, ce lien semble expliquer qu'un NUL désigne la fin d'une chaîne, tandis qu'un LF désigne la fin d'une ligne dans un fichier texte.
Et si un NUL est stored as 10
comme l'indique l'aide, qui est le même code que pour un LF, comment Vim est-il capable de faire la différence entre les 2?
Modifier 3 :
Peut-être qu'un LF et un NUL sont codés avec le même code décimal 10
, comme le dit l'aide. Et Vim fait la différence entre les 2 grâce au contexte. S'il rencontre un caractère dont le code décimal est 10
dans un tampon ou n'importe quel registre, à l'exception des registres de recherche et de commande, il l'interprète comme un LF.
Mais dans le registre de recherche ( :reg /
) il l'interprète comme un NUL car dans le contexte d'une recherche, Vim ne recherche qu'une chaîne où le concept de end of line in a file
n'a pas de sens car une chaîne n'est pas un fichier (ce qui est bizarre puisque vous pouvez utilise toujours l'atome \n
dans un motif recherché, mais ce n'est peut-être qu'une caractéristique du moteur d'expression régulière?). Il est donc automatiquement interprété 10
comme un NUL car c'est le concept le plus proche ( end of string
≈ end of line
).
Et de la même manière, sur la ligne de commande / registre de commande ( :reg :
), il interprète le code 10
comme un CR, car le concept de end of line in a file
n'a pas de sens ici. Le concept le plus proche est end of command
que Vim interprète 10
comme un CR, car frapper Enter
est le moyen de terminer / exécuter une commande et un CR est le même que frapper Enter
, car lorsque vous insérez un littéral avec <C-V><Enter>
, ^M
s'affiche.
Peut-être que l'interprétation du caractère dont le code est 10
change en fonction du contexte:
- fin de ligne dans un buffer (
^J
) - fin de chaîne dans une recherche (
^@
) - fin de commande sur la ligne de commande (
^M
)
la source
NULL
caractères inattendus est provoquée par la fonction C sous-jacente qui gère les chaînes. Cette explication de la façon dont C traite les chaînes auxquelles vous avez lié explique qu'en C interne délimite les chaînes avec aNULL
.NULL
s apparaissent assez rarement dans le texte pour en faire un bon caractère à cet effet. Une conséquence de cela est que si le programme C (vim) essayait de passer une chaîne "vide" dans une fonction C internesomeFunction(arg1, "")
où arg 2 était""
ie "l'élément entre les guillemets, qui est littéralement rien - un" vide ". un NULL peut apparaître, car il a été" ajouté "par l'implémentation C sous-jacente car il délimitait la chaîne. Je ne sais pas comment vous vérifieriez cela - mais cela vient à l'esprit comme une cause possible\r
et la\n
différence:substitute
.Réponses:
Tout d'abord, merci pour ce message très complet et réfléchi.
Après quelques tests, je suis arrivé à cette conclusion:
Les caractères de contrôle sont affichés en utilisant la notation caret:
^M
pour<CR>
(retour chariot) et^J
pour<LF>
(saut de ligne). Dans les tampons,<EOL>
(fin de ligne) sont affichés en tant que nouvelles lignes d'écran et sont saisis avec la touche Entrée.<EOL>
dépendent du format de fichier du tampon:<EOL> = <CR>|<LF>|<CR><LF>
pourmac|unix|dos
respectivement.Lors de l'édition d'un tampon, le format de fichier est toujours défini. Pour modifier le format de fichier d'un tampon ouvert, vous pouvez utiliser la commande suivante qui convertit
<EOL>
:Outre la conversion
<EOL>
, cette commande est convertie<LF>
en<CR>
lors du changement de format de fichier demac
enunix|dos
, et inversement<CR>
en<LF>
lors de la modification du format de fichier deunix|dos
enmac
. Pour voir les octets réels du tampon, vous pouvez utiliser la commande suivante qui transforme la représentation textuelle du tampon en sa représentation hexadécimale à l'aide de l'éditeur hexadécimal pratique xxd:Dans les registres (avec la commande montraient
:reg[isters]
ou:di[splay]
),<EOL>
sont toujours affichés comme^J
(mais tous ne^J
sont<EOL>
), quel que soit le format de fichier du tampon. Cependant<EOL>
sont stockés comme ils le devraient. Pour pouvoir distinguer visuellement réel^J
(c'est-à-dire<LF>
) des autres^J
(c'est-à-dire<EOL>
) dans les registres, vous pouvez utiliser la commande suivante qui affiche les valeurs hexadécimales au lieu de la notation caret des caractères de contrôle différents de<EOL>
:Dans les modèles de recherche et les chaînes de substitution:
Partout:
Cela montre que lorsque le format de fichier est
dos
, il est impossible de saisir<LF>
, puisque<EOL> = <CR><LF>
et<C-V><C-M>|<C-V><EOL> = <CR>
.Dans les chaînes de substitution:
les retours à la ligne différents de
<EOL>
sont interprétés comme<EOL>
;<EOL>
sont interprétés comme<NUL>
.Ainsi, selon 4.,
:%s[ubstitute]/\r/\r/g
remplace chaque nouvelle ligne différente de<EOL>
dans le tampon avec<EOL>
, tandis que:%s[ubstitute]/\n/\n/g
remplace chaque<EOL>
dans le tampon avec<NUL>
.Dans le registre de recherche
/
et le registre de commande:
,<EOL>
sont convertis ennouvelle ligne différente de celle
<EOL>
insérée à partir d'un registre avec/<C-R>{register}
ou:<C-R>{register}
respectivement;<NUL>
lorsqu'ils sont insérés à partir d'un registre avec:let @/=@{register}
ou:let @:=@{register}
respectivement.Dans les tampons, les sauts de ligne différents de
<EOL>
sont convertis en<EOL>
lorsqu'ils sont insérés à partir d'un registre en utilisanti<C-R>{register}
.Avant de copier
<LF>
du registre sans nom"
vers d'autres registres, vous devez le saisir<LF>
et le mettre dans le registre"
. Si le format de fichier estunix
, vous pouvez le faire en utilisantyy
sur une ligne vide; si le format de fichier estmac
, vous pouvez le faire en utilisanti<C-V><C-M><Esc>yl
; si le format de fichier estdos
, vous ne pouvez pas saisir<LF>
(cf. 5.).Maintenant, votre déclaration est partiellement fausse, car
vous n'utilisez pas la même méthode pour copier
<LF>
du registre"
dans le registre de recherche/
et le registre de commande:
. Vous utilisez:let @/=@"
pour copier dans le registre/
et:<C-R>"
pour copier dans le registre:
. Utiliser/<C-R>"
et:<C-R>"
respectivement vous donnera le même résultat (<CR>
) dans les deux cas;les conversions
<LF>
ont lieu avec vos deux méthodes de copie différentes uniquement lorsque le format de fichier estunix
. Si c'est le casmac
,<LF>
n'est pas converti lors de la copie dans le registre/
ou le registre:
, et si c'est le cas,dos
vous ne pouvez même pas entrer<LF>
.La bonne déclaration est donnée par 7. Mais je n'en connais vraiment pas les raisons.
la source