使用 vim 缓冲区中的文件名执行命令

使用 vim 缓冲区中的文件名执行命令

我正在和一些维基百科类似文件。这些文件在同一目录中有配套的 PNG 文件。它们以以下语法引用:

{{文件名.png}}

我想编写一个宏,它采用filename.png和理想情况下正在编辑的文件的路径,并将这些参数传递给xdg-open

到目前为止我最接近的结果是这样的:

:'<,'>!sed s/\{\\\|\}//g|xargs xdg-open

这很粗糙,抹去了当前行,要求我处于文件路径中,并要求我使用可视模式来突出显示文本......但它确实有效。

我很难找到可以帮助我安全地解析文件名的当前行,然后将当前文件的路径和目标文件名传递给xdg-openvim 命令行的文档。

完成后...理想情况下这将让我启动宏来查看嵌入的文件。


根据 G-Man 的回答和一些调整,以下方法效果很好:

:.w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's/^/"/' -e 's/}}.*/"/' | xargs xdg-open

"这会在路径/文件名的开头和结尾插入双引号( )字符,因此它支持包含空格、撇号(单引号)和其他一些特殊字符的名称。

答案1

  • 范围命令

    从中写入文本范围到管道(从文件缓冲区中删除它),运行命令在管道上,读取命令的标准输出并将其插入到缓冲区中范围是。这就是vim您正在使用的函数。该函数与sort命令配合使用非常有用。我不记得曾经见过任何其他情况下该vim函数有用;这似乎不是。

    你要

    范围 哇!命令
    写下范围到管道(但不从文件缓冲区中删除它),运行命令在管道上,并让命令的标准输出(如果有)直接进入屏幕(即vim的标准输出)。(范围w是可选的。

  • 范围可以是从一个标记到另一个标记('<并且'>是有效的标记),从一条线到另一条线,或者只是一条线。只要{{…}}一行只有一个,您就可以转到该行(无需突出显示它)并使用.{{…}}作为范围。如果文件中只有一个,则可以使用/{{.*}}/(或者/{{/,如果是唯一的)作为范围。因此,您的命令变为
    :/{{/哇!sed等等等等等等
  • 我更喜欢引用需要引用的字符串带引号,而不是向他们扔上一百万个反斜杠。我想这只是个人喜好;如果反斜杠对你有用,就用它们吧。
  • 花哨的正则表达式(用于|搜索一个或另一个模式)在世界上有其一席之地。我倾向于使用多个sed命令。再说一遍,随便吧。
  • 因此,对于你现在所做的事情,我的版本看起来是这样的:
    :/{{/哇!sed -e 's/.*{{//' -e 's/}}.*//' | xargs xdg-open
    这会删除{{和 之前的所有内容,也会删除}}和 之后的所有内容。但这仍然要求您位于 PNG 文件所在的目录中。
  • PNG 文件与文本文件位于同一目录中。值得注意的是,当您使用!from运行 shell 命令时,命令行中的vim未转义字符将替换为您当前正在编辑的文件的名称。(尝试一下:键入。)我们可以使用它来确定文件所在目录的路径名。因此,我们可以将上述命令改进为:%:!echo abc%def

    :/{{/哇!sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's|}}.*||' | xargs xdg-open
    第一个 sed 子命令s|.*{{|%{{|删除 之前的所有内容{{并将其替换为文件名, 并留下 {{。请注意,此子命令必须使用不会出现在路径/文件名中的(非空白)分隔符,因此我们不能使用/。如果您的目录名称或文件名中有竖线,请选择其他字符作为分隔符。第二个子命令,s|[^/]*{{||删除文件名部分文件%名,保留目录部分(如果有),并删除{{。第三个子命令s|}}.*||,与上一个命令中的第二个子命令 ( ) 相同s/}}.*//;它删除}}和其后的所有内容。

    虽然命令总是需要使用不出现在s/pattern/replacement/pattern或者replacement文本(或在出现分隔符时对其进行转义),这只是第一个问题s命令。我|在这三个命令中都使用了只是为了保持一致性。

总结

使用:

:/{{/w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's|}}.*||' | xargs xdg-open

PS,我假设您意识到如果文件名包含空格,这些将不起作用。

相关内容