VIM: Delete pattern IF submatch(1) is empty

百般思念 提交于 2019-12-11 04:15:18

问题


This command line parses a contact list document that may or may not have either a phone, email or web listed. If it has all three then everything works great - appending the return from the FormatContact() at the end of the line for data uploading:

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)

or, broken down:

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)

I created three separate searches so as not to make any ONE search fail if one atom failed to match because - again - the contact info may or may not exist per contact.

The Problem that solution created was that when the pattern does not match I get the whole @" into @a. Instead, I need it to be empty when the match does not occur. I need each variable represented (phone,email,web) whether it be empty or not.

  1. I see no flags that can be set in the substitution function that will do this.
  2. Is there a way to return "" if \1 is empty?
  3. Is there a way to create an optional atom so the search query(ies) could still account for an empty match so as to properly record it as empty?

回答1:


Instead of using substitutions that replace the whole captured text with its part of interest, one can match only that target part. Unlike substitution routines, matching ones either locate text following given pattern, or report that there is no such text. Thus, using matchstr() in preference to substitute(), the parsing code listed in the question can be transformed, as follows.

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]*')



回答2:


Just in case you want linewise processing, consider using in combination with :global, e.g.

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

This will print the matched text for any line that contained it, separated with newlines:

echo @a

The beautiful thing here, is that you can make it work with the last-used search-pattern very easily:

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


来源:https://stackoverflow.com/questions/8821858/vim-delete-pattern-if-submatch1-is-empty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!