VIM: Удалить шаблон, если субматч (1) пуст - PullRequest
1 голос
/ 11 января 2012

Эта командная строка анализирует документ списка контактов, который может содержать или не содержать телефон, электронную почту или Интернет. Если у него есть все три, то все работает отлично - добавляя возврат из 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. Есть ли способ создать необязательный атом, чтобы поисковый запрос (и) мог по-прежнему учитывать пустое совпадение, чтобы правильно записать его как пустое?

Ответы [ 2 ]

1 голос
/ 12 января 2012

Вместо использования замен, которые заменяют весь захваченный текст его часть интереса, можно сопоставить только эту целевую часть. В отличие от замены Подпрограммы, соответствующие из них, либо размещают текст по заданному шаблону, либо сообщают что такого текста нет. Таким образом, используя 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]*')
1 голос
/ 11 января 2012

На всякий случай, если вам нужна обработка аналогичным образом, рассмотрите возможность использования в сочетании с: global, например,

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

. При этом будет напечатан соответствующий текст для любой строки, содержащей его, отделенный символами новой строки:

echo @a

Прекрасная вещь в том, что вы можете легко заставить работать с последним использованным шаблоном поиска :

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