Regex чтобы вставить пробел в Vim

Я regex supernoob (просто читаю свои первые статьи о них), и в то же время работаю над более сильным использованием vim. Я хотел бы использовать регулярное выражение для поиска всех экземпляров двоеточия : которые не сопровождаются пробелом и вставить один пробел между эти двоеточия и любой персонаж после них.

если я начну с:

foo:bar

Я хотел бы закончить с

foo: bar

Я дошел до %s/:[a-z] но теперь я не знаю, что делать для следующей части %s заявление.

кроме того, как мне изменить :[a-z] заявление, чтобы убедиться, что он ловит все, что не пространство?

4 ответов


:%s/:\(\S\)/: /g

\S соответствует любому символу, который не является пробелом,но вам нужно помнить, что это не пробел. Это \(\) делает. Затем вы можете обратиться к нему с помощью замена.

таким образом, вы соответствуете :, некоторый символ без пробелов, а затем замените его на :, пробел и захваченный персонаж.


изменение этого, чтобы изменить только текст, когда есть только один : довольно прямолинейно. Как предлагали другие, использование некоторых утверждений нулевой ширины будет полезно.

:%s/:\@!<:[^:[:space:]]\@=/: /g

  • :\@!< любой не-:, включая начало линии. Это важная характеристика отрицательных утверждений lookahead/lookbehind. Это не требует, чтобы на самом деле был персонаж, просто нет :.

  • : соответствует требуемому двоеточие.

  • [^:[:space:]] вводит еще пару концепций регулярных выражений.

    • внешний [] коллекция. Коллекция используется для соответствия любому из символов, перечисленных внутри. Однако ведущий ^ отрицает это совпадение. Итак,[abc123] будет соответствовать a, b, c, 1, 2 или 3, а [^abc123] соответствует чему угодно, кроме этих символов.

    • [:space:] персонаж класс. Классы символов могут использоваться только внутри коллекции. [:space:] означает, неудивительно, любые пробелы. В большинстве реализаций он напрямую связан с результатом библиотеки C .

    связывая все это вместе, коллекция означает " соответствовать любому символу, который не является : или пробел".

  • \@= является положительным утверждением lookahead. Это относится к предыдущему атому (в данном случае collection) и означает, что коллекция необходима для успешного совпадения шаблона, но не будет частью заменяемого текста.

Итак, всякий раз, когда шаблон соответствует, мы просто заменяем : С собой и пространством.


вы хотите использовать отрицательное утверждение lookahead нулевой ширины, которое является причудливым способом сказать, что ищите символ, который не является пробелом, но не включайте его в матч:

:%s/: \@!/: /g

на \@! является отрицательным lookahead.


интересной особенностью Vim regex является наличие \zs и \ze. Другие двигатели могут иметь их тоже, но они не очень распространены.

цель \zs это отметить начало матча, и \ze конец. Например:

ab\zsc

игр c, только если перед вами есть ab. Аналогично:

a\zebc

игр a только если у вас есть bc после него. Вы можете смешать оба:

a\zsb\zec

игр b только если между a и c. Вы также можете создать совпадения нулевой ширины, которые идеально подходят для того, что вы пытаетесь сделать:

:%s/:\zs\ze\S/ /

ваш поиск не имеет размера, только позиции. И их вы заменяете этой позицией на " ". Кстати, \S означает любой символ, кроме пробелов.

:\zs\ze\S соответствует положению между двоеточием и чем-то не пробелом.


вы, вероятно, хотите использовать :[^ ] мАч все, кроме пробелов. Как упоминалось Мэттом, это заставит вашу замену заменить дополнительный символ.
Есть несколько способов избежать этого, вот 2, которые я считаю полезными.
1) заключите последнюю часть поискового термина в скобки \(\), это позволяет ссылаться на эту часть поисков в заменить термин /1.
Ваша последняя строка замены должна выглядеть так:

%s/:\([^ ]\)/: /g

2) завершите поисковый запрос с \ze это означает, что весь поисковый запрос должен быть выполнен для соответствия, но только часть до \ze будет higlighted / или заменено
Ваша последняя строка замены должна выглядеть так:

%s/:\ze[^ ]/: /g