Как изменить все слова в верхнем регистре на строчные, но исключить строковые литералы в Vim

У меня довольно длинный sql-скрипт, где все ключевые слова в верхнем регистре. Я хочу изменить их на строчные, но сохранить точные значения строковых литералов и собственные идентификаторы.
Например, в этом тексте:

KEYWORD BEFORE 'SOME STRING LITERAL' KEYWORD AFTER
mixedCaseValue  
MY_OWN_VARAIBLE
UGLY APPERCASE KEYWORDS, other text

Я хочу, чтобы только «KEYWORD BEFORE», «KEYWORD AFTER» и последнее «UGLY UPPERCASE KEYWORDS» были строчными, а все остальные остались нетронутыми.
Если я использую что-то вроде этого :%s/\<\u\+\>/\L&/g, это также влияет на текст внутри кавычек в первой строке.

У тебя есть идеи?


person east825    schedule 17.03.2012    source источник
comment
Помогает ли это, я не уверен, что вам здесь нужно - vim.wikia.com/wiki/Switching_case_of_characters   -  person Caffeinated    schedule 18.03.2012
comment
Не могли бы вы уточнить более строгое синтаксическое определение строкового литерала в используемом вами языке программирования? Могут ли эти строковые литералы в одинарных кавычках занимать несколько строк? Есть ли синтаксис для экранирования одинарных кавычек внутри строковых литералов?   -  person ib.    schedule 18.03.2012


Ответы (3)


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

:%s/\%(^\%([^']*'[^']*'\)*\)\@<=[^']\+/\=substitute(submatch(0),'\<\u\+\>','\L&','g')/g
person ib.    schedule 18.03.2012
comment
Это почти работает — если вы запустите его для моего примера, он также изменит mixedCaseValue и MY_OWN_VARAIBLE. Но теперь я знаю, в каком направлении идти. Спасибо! - person east825; 18.03.2012
comment
@ east825: Я пропустил, что вы хотели бы переводить в нижний регистр не все, кроме строковых литералов, а только слова, написанные в верхнем регистре. Предложенную мной команду можно изменить для этого; пожалуйста, смотрите обновление ответа. - person ib.; 18.03.2012
comment
ВОТ ЭТО ДА! Это огромно! И вроде работает именно так, как я хотел (по крайней мере, на первый взгляд). Я думаю, что ты победитель. Теперь мне нужно потратить некоторое время на то, чтобы копаться в помощи Vim, чтобы понять, что он делает) - person east825; 19.03.2012

В одну сторону:

:%v/'/s/\(^\|\s\)\@<=\u\+\(\s\|,\)\@=/\L&/g

Объяснение:

%                      # Range: All file.
v/pattern/command      # Apply command to all lines that doesn't match pattern
'                      # The pattern, so apply substitution to lines that doesn't have it.
s/string/replacement/  # Replacement command.
\(^\|\s\)\@<=          # Zero-width preceding match: Beginning of line or a space.
\u\+                   # One or more alphabetic uppercase letters.
\(\s\|,\)\@=           # Zero-width positive match: Space or comma.
\L&                    # Lowercase the string matched
/g                     # Apply globally: Many times for each line.

Результат:

'SOME STRING LITERAL'  
mixedCaseValue  
MY_OWN_VARAIBLE
ugly appercase keywords, other text
person Birei    schedule 17.03.2012
comment
Хорошее решение! Раньше я не знал о '\@‹=' и '\@='. Думал, что без v/ в начале будет даже лучше. Из-за этого этот шаблон не соответствует ключевому слову upperace в тех же строках со строковыми литералами (в примере я не показывал такой случай). И по крайней мере с $ внутри вторых фигурных скобок, чтобы соответствовать ключевым словам в конце строки. - person east825; 18.03.2012
comment
@east825: Да. Ты прав. Это конкретное решение для вашего примера, но оно может не сработать во многих других случаях. Дополните свой пример другими возможностями, и больше пользователей предложат лучший подход. - person Birei; 18.03.2012
comment
Извините, моя ошибка - без v/ он также будет соответствовать словам в верхнем регистре внутри кавычек (например, «STRING»). - person east825; 18.03.2012

Моя внутренняя любящая живость душа сжимается, чтобы написать это, но...

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

В качестве альтернативы, если есть только несколько строковых литералов, которые не нужно трогать, измените их на какую-либо другую строку, чтобы глобальная замена не изменила их, выполните глобальную замену, а затем измените их обратно. Тоже грубо, но эффективно.

Я чувствую себя грязным.

person David Pope    schedule 18.03.2012
comment
На самом деле я уже это сделал) Мне просто интересно, может быть кто-нибудь знает какой-нибудь хороший шаблон, который может делать такую ​​​​подстановку автоматически. - person east825; 19.03.2012