Reputation: 456
how can I escape the regexp \([''"]\)\(.\{-}\)\1
and *test
in the following function
:%s/.*/\=substitute(submatch(0),"\([''"]\)\(.\{-}\)\1","*test","g")/
the first regex matches anything between quotation in each line and replace it with what ever matches the second regexp at the same line
thanks, Best
Edit: example:
select "foo" as subject from table where [subject_test]=true
union
select "bar" as subject from table where [subject_test]=true
should become
select "foo" as subject from table where [subject_foo]=true
union
select "bar" as subject from table where [subject_bar]=true
Upvotes: 1
Views: 3929
Reputation: 1589
Don't know if I understand your question correctly.
When using the function substitute()
there are other rules for pattern than when using e.g. :s///
.
See this: :h substitute()
Some parts from that:
...
But the matching with {pat} is always done like the 'magic' option is set and 'cpoptions' is empty (to make scripts portable). 'ignorecase' is still relevant. 'smartcase' is not used.
...
Note that some codes in {sub} have a special meaning |sub-replace-special|. For example, to replace something with "\n" (two characters), use "\\n" or '\n'.
It's not clearly how to use special regexp codes but they should be used with double backslash if you are using double quotes for the pattern string, "\\"
means the character \
, and is the same as '\'
.
These should be equivalent when using the function substitute():
'\([a-z]\)'
"\\([a-z]\\)"
And my favorite, using \v
("very magic") so I don't have to backslash some regexp expressions:
"\\v([a-z])"
Your example should then be (I have NOT considered if your pattern is correct or not)
substitute(submatch(0), '\v([''"])(.{-})\1', "*test", "g")
Or:
substitute(submatch(0), "\\v(['\"])(.{-})\\1", "*test", "g")
The tricky part is that in the function substitute() you are using the pattern as a string, that is not the situation when normally using pattern in the command line in e.g. :s///
.
EDIT (again due to comment by OP):
Can't say that I understand the use of your example, but I couldn't resist to try to fix it with an ex command like the one in your question (I'm trying to learn about VIM at the same time). Here is a command that works, and gives the result you want, but again, I don't understand what the use is.
But it seems that the question is really to learn how to escape regexp in a string.
If the "string" is always before what to substitute (and only substitutes one test
for each ""):
:%s/\v"([^"]+)".*_\zstest/\1/g
Explanation
\zs
= start match, \v
= use "very magic""([^"]+)"
"match" all characters except "
(minimum 1) between "
and "
.*
all characters up to next expression:_\zstest
"match" _test
, but \zs
makes the "real match" to start after that, so it's only test
that will be substituted./\1/
replace with submatch number 1changed This wasn't "safe", I added some longer match (from @Kent's answer), and also make sure only lines that have "<any characters>"
are processed.
If the "string" can be before or after what to substitute
:g/\v"[^"]+"/y w | s/\v\[\w*_\zstest\ze\]/\=matchstr(@w, '\v"\zs[^"]+\ze"')/g
Explanation
\v
= "very magic"g/\v"[^"]+"
use lines that have "<some text>"
/y w
yank line to reg. w
(instead of using getline())|
to have one more command\zs
= start match, \ze
= end match (quicker than using look-ahead etc.)\w
same as using [0-9A-Za-z_]
\[\w*_\zstest\ze\]
"match" [<almost any characters>_test]
, but the "real match" to substitute is test
because of the \zs
and \ze
matchstr(str, match)
returns the match
in str
matchstr(@w, '\v"\zs[^"]+\ze"')
get the characters between "
and "
from the line (using reg w
)test
/g
do it for all occurrences of [<almost any characters>_test]
in the lineUpvotes: 2
Reputation: 16188
To escape characters which are using in a substitute function I use escape()
Escape the characters in {chars} that occur in {string} with a backslash.
Example:
:echo escape('c:\program files\vim', ' \')
Results in:
c:\\program\ files\\vim
For you example you can use escape('\([''"]\)\(.\{-}\)\1','\')
.
This will expand to: \\(['"]\\)\\(.\\{-}\\)\\1
Upvotes: 1
Reputation: 322
In VimL, single-quoted strings don't interpolate backslashes, and double-quoted strings do.
So, note the difference between :echo '\'
and :echo "\\"
. In your example, you used double quotes, and since you're not turning off magic, you have a ton of escaping to do. See :help magic
... Since I found out about \v
, people tell me I'm much more pleasant to be around.
Upvotes: 0
Reputation: 195049
is this ok for you?
%s/\[.\{-}_\zstest\ze\]/\=split(getline('.'), '"')[1]/
this works too (with your example), and straightforward:
%s/\[subject_test\]/\="[subject_".split(getline("."),'"')[1]."]"/
Upvotes: 1