如何在Vim脚本中使用'^@'?

4
我正在尝试解决在Vim脚本中使用^@(即)字符的问题。我可以将它们插入脚本,但是当脚本运行时,似乎该行在^@处被截断。
到目前为止,我采用了笨拙的解决方案:将^@存储在变量中,然后在脚本中引用该变量,以替代引用字面值^@的方式。有人能告诉我这里发生了什么吗?是否有更好的方法来解决这个问题?
2个回答

5
这就是为什么我从不在脚本中使用原始的特殊字符值的一个原因。当 ^@ 无法正常工作时,映射中的字符串 <C-@> 的效果如预期一样,因此您可以使用其中之一。
nnoremap <C-@> {rhs}
nnoremap <Nul> {rhs}

很奇怪,但你不能在这里使用<Char-0x0>。关于字符串中的空字节,请注意以下几点:

  1. 将空字节插入字符串会截断它:vim使用旧的C风格字符串,以空字节结尾,因此它不能出现在字符串中。这些字符串非常低效,因此如果您想生成非常大的文本,请尝试将其累加到行列表中(使用setline非常快,因为缓冲区表示为行列表)。
  2. 大多数返回字符串列表的函数(如readfilegetline(start,end))或接受字符串列表的函数(如writefilesetlineappend)将\n(NL)视为Null。这也是缓冲区行的内部表示,参见:h NL-used-for-Nul
  3. 如果您尝试将\n字符插入命令行,则会显示Null(但实际上是换行)。如果您想编辑带有\n的文件名(在*nix上可能存在),则需要在换行符前加上反斜杠。

我正在尝试使用redirect =>>将消息缓冲区的输出捕获到一个变量中。当我捕获由嵌入式python命令生成的输出时,重定向的文本中有^@字符,似乎是行结束符。我需要一些方法来替换这些字符的实际行结束符。我找到的唯一方法是将重定向文本的第一个字符(似乎也总是^@)捕获到一个变量中。然后我可以在替换命令中引用该变量。我假设有一种更可靠的方法将^@值存入变量中:例如,let myvar = 0x0 - Herbert Sitz
@Herbert Sitz。字符串变量中不能有null。如果您想用null替换文字“^@”(两个字符),唯一的方法是将整个字符串转换为字节列表(由整数值表示)([Int]),然后对其进行操作。或者将此字符串传递到Python脚本中,进行替换,永远不要传回vim。 - ZyX
1
@Herbert Sitz 如果您正在尝试解析由vim脚本重新抛出的python异常,那么throw命令显示的^@实际上是一个换行符:throw假定异常消息中没有换行符,并根据:h NL-used-for-Nul显示换行符。因此,类似于substitute(string, '\^@', "\n", 'g')的东西就足够了。 - ZyX
1
谢谢,那个替换方法对我来说并没有完全奏效。可能是我漏掉了什么,但是字符串似乎是以空字符作为换行符存储的。因此,它实际上没有替换任何内容,当我将替换后的字符串附加到缓冲区时,^@会出现而不是换行符。我通过附加字符串然后执行:s/^@/\r/g来解决这个问题。我也可以使用:let mylist=split(mystring,'^@')将字符串转换为列表。 - Herbert Sitz
我使用以下代码... let result = substitute(str, "\n", "", 'g') - Wayne

2

字节ctrl-@也被称为'\0'。许多语言、程序等将其用作“字符串结尾”标记,因此vim在这里混淆并不奇怪。如果你必须在脚本字符串中间使用这个字节,那么你的解决方法似乎是不错的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接