Точное совпадение строк в vim? (Например, режим 'regex-off' меньше.) - PullRequest
35 голосов
/ 11 октября 2009

В vim я часто хочу искать строку с привередливыми символами, которые нужно экранировать. Есть ли способ, которым я могу отключить значение всех специальных символов, например, режим regex-off less или fgrep ?

Я имею дело с особенно волосатыми нитями; Вот пример:

((N/N)/(N/N))/N

Отсутствие экранирования каких-либо символов для поиска в vim может значительно сэкономить время.

\ V в Vim помогает с некоторыми метасимволами, но критически не / или \.

<ч /> Спасибо всем! В конце я добавил это в свой .vimrc:

command! -nargs=1 S let @/ = escape('<args>', '\')
nmap <Leader>S :execute(":S " . input('Regex-off: /'))<CR>

Ответы [ 3 ]

31 голосов
/ 11 октября 2009

В зависимости от конкретной строки, которую вы ищете, префикс \V, вероятно, поможет.
См :help \V:

after:    \v       \m       \M       \V         matches ~
                'magic' 'nomagic'    
          $        $        $        \$         matches end-of-line
          .        .        \.       \.         matches any character
          *        *        \*       \*         any number of the previous atom
          ()       \(\)     \(\)     \(\)       grouping into an atom
          |        \|       \|       \|         separating alternatives
          \a       \a       \a       \a         alphabetic character
          \\       \\       \\       \\         literal backslash
          \.       \.       .        .          literal dot
          \{       {        {        {          literal '{'
          a        a        a        a          literal 'a'

Поэтому, если у меня есть строка hello.*$world, я могу использовать команду /\V.*$, чтобы найти только .*$ - единственная часть строки , которая должна быть экранирована, - это еще одна обратная косая черта, но вы все еще можете выполнять группировку и т. д., экранируя специальный символ.


Еще одна команда, которую вы можете использовать, чтобы «избежать» прямой косой черты:
:g #\V((N/N)/(N/N))/N#   

Команда :g является глобальным поиском, отмечая, что:

:[range]g[lobal]/{pattern}/[cmd]
                        Execute the Ex command [cmd] (default ":p") on the
                        lines within [range] where {pattern} matches.

Instead of the '/' which surrounds the {pattern}, you can use any other
single byte character, but not an alphanumeric character, '\', '"' or '|'.
This is useful if you want to include a '/' in the search pattern or
replacement string.

Итак, где я использовал #, вы могли бы использовать ?, @ или любой другой символ, отвечающий вышеуказанному условию. Уловка этой команды :g в том, что она ожидает команду в конце, поэтому, если у вас нет завершающего пробела после последнего символа, она не будет выполнять поиск, как вы ожидаете. И снова, даже если вы используете \V, вам все равно придется избегать обратной косой черты.

Если это все еще не обрезает его для вас, в этом сообщении Nabble есть предложение, которое принимает буквенную строку со встроенными обратными слешами и другими специальными символами Vim и утверждает, что ищет для этого без проблем; но это требует создания функции Vim, которая может быть или не быть приемлемой в вашей среде.

21 голосов
/ 11 октября 2009

Глядя на ваш конкретный пример, возможно, самый простой способ сделать это (так как \ V здесь не поможет) - это использовать ? вместо /: тогда вам не придется выходить из / s:

?((N/N)/(N/N))/N

Это будет поиск назад, а не вперед, но вы всегда можете сделать 'N' вместо 'n', чтобы искать вперед после первого хода. Или вы можете нажать /, а затем клавишу курсора вверх, чтобы автоматически убрать косую черту.

Тем не менее, вы ничего не можете сделать, избежав обратной косой черты. Я думаю, вы могли бы сделать:

:let @/ = escape(pattern, '\')

, а затем используйте n для поиска, но это, вероятно, не намного проще. Лучшее, что я могу придумать, это:

:command! -nargs=1 S let @/ = escape('<args>', '\')

Затем выполните:

:S (N)/(N+1)\(N)
n
5 голосов
/ 12 октября 2009

Может быть, что-то вроде этого:

nmap <Leader>s :execute '/\V' . escape(input('/'), '\\/')<CR>

Он выдаст вам приглашение / и будет вести себя иначе, как встроенный поиск, но не будет выполнять поиск по мере ввода или другие подобные вкусности.

...