【问题标题】:Vim: Delete the text matching a pattern IF submatch(1) is emptyVim:如果 submatch(1) 为空,则删除匹配模式的文本
【发布时间】:2020-02-22 15:23:03
【问题描述】:

此命令行解析联系人列表文档,该文档可能列出也可能没有列出电话、电子邮件或网络。如果它具有所有三个,那么一切都很好 - 将来自 FormatContact() 的返回附加到数据上传的行尾:

silent!/^\d/+1|ki|/\n^\d\|\%$/-1|kj|'i,'jd|let @a = substitute(@",'\s*Phone: \([^,]*\)\_.*','\1',"")|let @b = substitute(@",'^\_.*E-mail:\s\[\d*\]\([-_@.0-9a-zA-Z]*\)\_.*','\1',"")|let @c = substitute(@",'^\_.*Web site:\s*\[\d*\]\([-_.:/0-9a-zA-Z]*\)\_.*','\1',"")|?^\d\+?s/$/\=','.FormatContact(@a,@b,@c)

或者,分解:

silent!/^\d/+1|ki|/\n^\d\|\%$/-1|kj|'i,'jd
let @a = substitute(@",'\s*Phone: \([^,]*\)\_.*','\1',"")
let @b = substitute(@",'^\_.*E-mail:\s\[\d*\]\([-_@.0-9a-zA-Z]*\)\_.*','\1',"")
let @c = substitute(@",'^\_.*Web site:\s*\[\d*\]\([-_.:/0-9a-zA-Z]*\)\_.*','\1',"")
?^\d\+?s/$/\=','.FormatContact(@a,@b,@c)

我创建了三个单独的搜索,以便在一个原子匹配失败时不会使任何一次搜索失败,因为 - 再次 - 每个联系人可能存在或可能不存在联系信息。

问题该解决方案创建的是,当模式不匹配时,我将整个 @" 放入 @a。相反,当匹配不发生时,我需要它为空。我需要每个变量都表示(电话、电子邮件、网络),无论它是否为空。

  1. 我看不到可以在替换函数中设置的标志 会这样做。
  2. 如果 \1 为空,有没有办法返回 ""?
  3. 有没有办法创建一个可选原子,以便搜索查询仍然可以解释一个空匹配,从而正确地将其记录为空?

【问题讨论】:

  • 你能把你想要做什么更清楚一点吗?您是否正在逐行处理输入?谁首先拉动选择? @a 将在哪里使用。 (我尽我所能从中得到一些简洁的东西,但是没有编写一个 vimscript 函数对我来说没有任何效果
  • @sehe 帖子已更新。

标签: regex vim substitution


【解决方案1】:

而不是使用替换整个捕获的文本 对于感兴趣的部分,只能匹配该目标部分。不像 替换例程,匹配的要么找到符合的文本 到给定的模式,或报告没有这样的文本。因此, 使用matchstr() 函数而不是substitute(), 问题中列出的解析代码可以更改如下:

let @a = matchstr(@", '\<Phone:\s*\zs[^,]*')
let @b = matchstr(@", '\<E-mail:\s*\[\d*\]\zs[-_@.0-9a-zA-Z]*')
let @c = matchstr(@", '\<Web site:\s*\[\d*\]\zs[-_.:/0-9a-zA-Z]*')

【讨论】:

  • 大师@ib。你太棒了! :) 我实际上使用从你那里学到的另一种技术解决了这个问题(“!=”匹配“FormatContact”函数中的单词),但我知道有更好的方法 - 我实现了你上面的帖子。我想我在 vim 帮助中阅读了有关 matchstr 的内容,但是要记住所有内容太多了。非常感谢(再次)。
  • 大师@ib。你对我帮助很大。我会回来更多! :) 你能看看这篇文章吗? stackoverflow.com/questions/8887207/…谢谢!
  • 我收到了你的电子邮件。谢谢你追我!私下回复。到今天为止,您应该已经从我的 gmail 帐户收到了我的电子邮件。
【解决方案2】:

如果您想要逐行处理,请考虑与 :global 结合使用,例如

let @a=""
g/text to match/let @A=substitute(getline("."), '^.*\(' . @/ . '\).*$', '\1\r', '')

这将打印包含它的任何行的匹配文本,用换行符分隔:

echo @a

这里的美妙之处在于,您可以非常轻松地使其与上次使用的搜索模式一起工作:

g//let @A=substitute(getline("."), '^.*\(' . @/ . '\).*$', '\1\r', '')

【讨论】:

  • 谢谢@sehe 这是创造性思维,我会记住的。我根据您的要求重新发布了 OP,以使其更清晰。请再看看。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多