问题
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.
- I see no flags that can be set in the substitution function that will do this.
- Is there a way to return "" if \1 is empty?
- 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