Найти и заменить с помощью регулярных выражений


26

У меня есть файл с кучей пользовательских настроек по умолчанию. Я хочу изменить часть текста, но я с трудом придумываю совпадения и заменители. Используя следующий пример:

###############################################################################
# Trackpad, mouse, keyboard, Bluetooth accessories, and input                 #
###############################################################################

# Trackpad: enable tap to click for this user and for the login screen
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true

Я хотел бы заменить # Trackpad: ...наrunning "Trackpad: ..."

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

/\n\n#\s(.*)/g

Если я попытаюсь использовать это в Vim, это не сработает для меня:

:/\n\n#\s(.*)/running "\1"/g

Я думаю, моя проблема сводится к двум конкретным вопросам:

  1. Как я могу избежать поиска \nсимволов, и вместо этого убедиться, что #не появляется в конце группы поиска?
  2. Как я могу эффективно использовать группы захвата?

Ниже приведены отличные ответы. Трудно выбрать между всеми тремя, однако я считаю, что выбранный ответ является наиболее точным для моей первоначальной спецификации. Я рекомендую вам попробовать все три ответа с настоящим файлом, чтобы увидеть, как вы к ним относитесь.

Ответы:


18

Просто чтобы прояснить ... Я думаю, что вы просили, чтобы это было результатом замены?

###############################################################################
# Trackpad, mouse, keyboard, Bluetooth accessories, and input                 #
###############################################################################

running "Trackpad: enable tap to click for this user and for the login screen"
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true

В этом случае я рекомендую следующую команду:

:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/

Объяснение картины

:s/PATTERN/REPLACEMENT/является заменой команды. Знак процента :%sпозволяет работать с целым файлом, а не только с текущей строкой.

Это \n\nговорит о том, что линия интереса должна появляться после пустой строки. Если вас не волнует предыдущая пустая строка, тогда ^будет достаточно.

#\s\+соответствует хэш-символу, за которым следует один или несколько пробельных символов. \(.*\)захватывает весь последующий текст в строке

Объяснение заменяющего текста

^M^Mвставляет два конца линий, чтобы заменить те \n\n, которые присутствовали в шаблоне. В противном случае текст будет перемещен в конец строки, предшествующей пустой строке. Для ввода каждого ^Mнажмите Ctrl-V Ctrl-M.

Затем вставьте строку running, а затем все, что было записано в скобках в двойных кавычках.


Я не могу отредактировать ваш ответ, но полагаю, что вы имели в виду :%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/(добавили «волшебный» флаг). Действительно трудно выбрать правильный ответ для моего первоначального вопроса, но я чувствую, что этот ответ наиболее близок к моему первоначальному ожидаемому ответу. Это также единственный файл, который работает по всему файлу без необходимости выбора диапазона.
squarefrog

1
IIRC вы можете использовать \rвместо того, ^Mчтобы получить новые строки?
Муру

11

Я бы использовал что-то вроде:

:s/^#\s\+\(.\{-}\):/running "\1":/
  • ^#чтобы соответствовать #символу, закрепленному в начале строки (это отвечает на вопрос 1)
  • \s\+ соответствовать любому пробелу один или несколько раз
  • \( создать группу (это отвечает на вопрос 2)
  • .\{-}\сопоставлять любой символ 0 или более раз не жадным способом ; это отличается от того, .*что он пытается соответствовать как можно меньше, а не как можно больше. Попробуйте добавить :символ в комментарии, чтобы понять, почему это важно
  • \) закончить подгруппу.
  • : соответствует буквальному :

Затем мы заменяем это текстом, который вы хотите, и используем \1для ссылки на захваченную нами группу.

Я придумал что-то, используя тестер регулярных выражений

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

Сегодня так называемые "Perl-совместимые" регулярные выражения являются де-факто по умолчанию в большинстве языков, но регулярные выражения Vim не совместимы с Perl-совместимыми выражениями! Синтаксис Vim regexp восходит, по крайней мере, к 70-м годам, когда Perl еще не было.

Вы можете увидеть это с подгруппами, где вы должны использовать, \(а не ((это совместимо с «базовым» синтаксисом POSIX, но не с более распространенным «расширенным» синтаксисом POSIX или синтаксисом Perl). Вы можете контролировать это, добавляя \vфлаг в шаблон (см. :help /\vПодробности), это сделает его «более совместимым», но не полностью (вам все равно придется использовать, например, .{-}для не жадных совпадений)

Таким образом, это может объяснить, почему использование «тестера регулярных выражений» почти, но не совсем, работает.

http://www.vimregex.com/ в качестве хорошего обзора / чит-листа Vim regexps.


1
Отличный ответ, особенно с тем, почему регулярное выражение! = Регулярное выражение. Что касается поиска и замены, это немного сложно, так как комментарий может иметь или не иметь :. Подробности смотрите в полном файле github.com/squarefrog/dotfiles/blob/master/osx/…
squarefrog

8

Вы можете:

  • поиск строк, которые не заканчиваются на #::/[^#]$/
  • заменить #\s(.*)в начале строки:s/\v^#\s(.*)/running "\1"/

Чтобы использовать группы, вам необходимо:

  • экранировать скобки, чтобы они стали частью синтаксиса регулярных выражений: \(.*\)или
  • используйте «магию» , начав выражение с \v:s/\v...

Сочетая это:

:/[^#]$/s/\v^#\s(.*)/running "\1"/

1
Это прекрасно работает, спасибо, что включили объяснение того, что означают теги, а не просто текст, который мне нужно было написать.
squarefrog

Спасибо за разъяснение, что скобки должны быть экранированы, чтобы стать частью синтаксиса регулярных выражений. У меня всегда была проблема с группами регулярных выражений в том, чтобы заставить их работать.
Адама
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.