You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

探究Vim中|、<Bar>和\|的统一解析规则

Vim中|、<Bar>和\|的行为差异实验

我整理了多组实验来对比Vim命令里|、<Bar>和\|在不同场景下的行为,下面是具体的测试过程和结论:

场景1:Shell命令

:!uname | new
/bin/bash: new: command not found

:!uname <Bar> new
/bin/bash: Bar: no such file or directory

:!uname \| new
usage: uname [-amnprsv]

:!uname | grep i
Darwin

结论:

  • |会作为字面量|传递给shell。
  • <Bar>会作为字面量<Bar>传递给shell,被当作无效的I/O重定向参数。
  • \|会作为字面量|传递给shell。

这个场景里三者的行为逻辑很直观,输入的内容会直接传递给shell执行。

场景2:调用Shell命令的用户自定义命令

:command! A !uname | new
:A
/bin/bash: new: command not found

:command! A !uname <Bar> new
:A
/bin/bash: new: command not found

:command! A !uname \| new
:A
usage: uname [-amnprsv]

:command! A !uname | grep i
:A
Darwin

:command! A !uname <Bar> grep i
:A
Darwin

结论:

  • |和<Bar>行为一致,都会作为|传递给shell执行管道操作。
  • \|则会作为字面量\|传递给shell,导致uname命令因参数错误报错。

场景3:调用Shell命令的映射

:map ,a :!uname | new<CR>
,a
# 执行:map命令时就创建了新窗口;按下,a时,命令行模式会输入`!uname`

:map ,a :!uname <Bar> new
,a
# 按下,a时,命令行模式会输入`:!uname | new`

:map ,a :!uname \| new
,a
# 按下,a时,命令行模式会输入`:!uname | new`

结论:

  • |的行为特殊,会被当作:map命令和后续Vim命令new的分隔符,导致映射定义时就执行了new,而映射触发时只执行前半部分命令。
  • <Bar>和\|行为一致,映射触发时会被转换为|,完整执行整个shell命令。

场景4:接受参数的Vim命令

:new | vnew
# 创建两个分割窗口(new和vnew分别执行)

:new <Bar> vnew
# 创建一个分割窗口,文件名是`<Bar> vnew`

:new \| vnew
# 创建一个分割窗口,文件名是`| vnew`

结论:

  • |是Vim的命令分隔符,用来分隔两个独立的Vim命令。
  • <Bar>和\|会被当作new命令的字面量参数,作为文件名使用。

场景5:调用接受参数Vim命令的用户自定义命令

:command! A new | vnew
:A
# 创建两个分割窗口

:command! A new <Bar> vnew
:A
# 创建两个分割窗口

:command! A new \| vnew
:A
# 创建一个分割窗口,文件名是`| vnew`

结论:

  • |和<Bar>都会被当作命令分隔符,让new和vnew分别执行。
  • \|则会被当作new的字面量参数,只执行单个new命令。
    这个结论和场景2的逻辑一致。

场景6:调用接受参数Vim命令的映射

:map ,a :new | vnew
,a
# 执行:map命令时就创建了新窗口;按下,a时,命令行模式会输入`new`

:map ,a :new <Bar> vnew
,a
# 按下,a时,命令行模式会输入`:new | vnew`

:map ,a :new \| vnew
,a
# 按下,a时,命令行模式会输入`:new | vnew`

结论:

  • |会被当作:map命令和后续Vim命令vnew的分隔符,导致映射定义时就执行了vnew,触发时只执行前半部分。
  • <Bar>和\|会被转换为|,触发时完整执行两个Vim命令。
    这个结论和场景3一致,本质是通过:map将按键映射为命令行模式的完整命令。

场景7:不接受参数的Vim命令

:bn | bn
# 跳转到下下个缓冲区(执行两次bn)

:bn <Bar> bn
E488: Trailing characters

:bn \| bn
# 只跳转到下一个缓冲区(`\| bn`被忽略了?)

结论:

  • 这个场景里|、<Bar>和\|三者行为完全不同:
    • |作为命令分隔符,执行两次bn;
    • <Bar>会被当作bn的无效参数,触发报错;
    • \|会被忽略,只执行一次bn。

场景8:调用不接受参数Vim命令的用户自定义命令

:command! A bn | bn
:A
# 跳转到下下个缓冲区

:command! A bn <Bar> bn
:A
# 跳转到下下个缓冲区

:command! A bn \| bn
:A
# 只跳转到下一个缓冲区

结论:

  • |和<Bar>都会被当作命令分隔符,执行两次bn;
  • \|则会被忽略,只执行一次bn。

内容的提问来源于stack exchange,提问作者Lone Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:06:31