Reputation: 909
I got rather long sql script where all keyword are uppercase. I want to change them to lowercase, but preserve exact values of string literals and my own identifers.
For example, in this text:
KEYWORD BEFORE 'SOME STRING LITERAL' KEYWORD AFTER
mixedCaseValue
MY_OWN_VARAIBLE
UGLY APPERCASE KEYWORDS, other text
I want only 'KEYWORD BEFORE', 'KEYWORD AFTER' and last 'UGLY UPPERCASE KEYWORDS' to be lowercase and all other left intact.
If I use something like this :%s/\<\u\+\>/\L&/g
, text inside quotes on the first line is also affected.
Do you have any ideas?
Upvotes: 1
Views: 2646
Reputation: 6587
My inner vim-loving soul cringes to write these, but...
If this is something you don't have to do frequently, you might just brute-force it by appending the c
flag onto your substitution command to prompt for confirmation of each change; you should be able to blow through a lot of script quickly, if you can put up with the tedium. It might be faster this way (in the short term) than by spending time crafting a good substitution command.
Alternatively, if there are only a handful of string literals that need to not be touched, change those to some other string so the global substitution doesn't change them, do the global substitution, and then change them back. Also gross but effective.
Ugh, I feel dirty.
Upvotes: 1
Reputation: 28944
Assuming that string literals do not span over multiple lines, and that there is no syntax for escaping single quotes inside string literals, I would use the following substitution command.
:%s/\%(^\%([^']*'[^']*'\)*\)\@<=[^']\+/\=substitute(submatch(0),'\<\u\+\>','\L&','g')/g
Upvotes: 1
Reputation: 36262
One way:
:%v/'/s/\(^\|\s\)\@<=\u\+\(\s\|,\)\@=/\L&/g
Explanation:
% # 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.
Result:
'SOME STRING LITERAL'
mixedCaseValue
MY_OWN_VARAIBLE
ugly appercase keywords, other text
Upvotes: 2