函数中的Vim转义字符

时间:2013-02-17 10:19:12

标签: regex vim

如何逃避正则表达式\([''"]\)\(.\{-}\)\1*test 在以下功能

:%s/.*/\=substitute(submatch(0),"\([''"]\)\(.\{-}\)\1","*test","g")/

第一个正则表达式匹配每行中引号之间的任何内容,并将其替换为与同一行中的第二个正则表达式匹配的内容

感谢, 最好

编辑: 例如:

select "foo" as subject from table where [subject_test]=true
union
select "bar" as subject from table where [subject_test]=true

应该成为

select "foo" as subject from table where [subject_foo]=true
union
select "bar" as subject from table where [subject_bar]=true

4 个答案:

答案 0 :(得分:2)

不知道我是否理解你的问题。

使用函数substitute()时,模式的其他规则比使用例如:s///
见::h substitute()
部分内容来自:

  

...
  但与{pat}的匹配总是像“魔法”一样完成。选项是   设置和' cpoptions'是空的(使脚本可移植)。   '忽略大小写'仍然相关。 '智能大小写'不使用。
  ...
  请注意,{sub}中的某些代码具有特殊含义   |子取代,特别|。例如,用" \ n"替换某些东西。   (两个字符),使用" \\ n"或者' \ n'。

目前还不清楚如何使用特殊的正则表达式代码,但如果您对模式字符串使用双引号,则应使用双反斜杠,"\\"表示字符\,以及与'\'相同。
使用函数替换()时,这些应该是等效的:
'\([a-z]\)'
"\\([a-z]\\)"
我最喜欢的是\v("非常神奇的")所以我不必反斜杠一些正则表达式:
"\\v([a-z])"

那么你的例子应该是(我没有考虑你的模式是否正确

substitute(submatch(0), '\v([''"])(.{-})\1', "*test", "g")
Or:
substitute(submatch(0), "\\v(['\"])(.{-})\\1", "*test", "g")

棘手的部分是在函数substitute()中使用模式作为字符串,这不是通常在命令行中使用模式的情况。 :s///


编辑(再次由于OP的评论):
不能说我理解你的例子的用法,但我无法用你问题中的ex命令来解决它(我试图在VIM上学习VIM)同一时间)。这是一个有效的命令,并给出你想要的结果,但同样,我不明白它的用途。
但似乎问题是学习如何在字符串中逃避正则表达式 如果"字符串"总是在替换之前(并且只为每个"")替换一个test

:%s/\v"([^"]+)".*_\zstest/\1/g

<强>解释

  • \zs =开始匹配,\v =使用&#34;非常神奇&#34;
  • "([^"]+)"&#34;匹配&#34;除""之间的"(最少1)之外的所有字符 (&#34;真正的比赛&#34;还没有开始,但是括号中的匹配仍然是1号子匹配)
  • .*所有字符到下一个表达式:
  • _\zstest&#34;匹配&#34; _test,但是\zs使得#34;真正的匹配&#34;在此之后开始,因此只有test将被替换。
  • /\1/替换为子匹配编号1

已更改这不安全&#34;,我添加了一些更长的匹配(来自 @Kent &#39;答案),并确保只处理"<any characters>"的行 如果&#34;字符串&#34;可以在替代之前或之后

:g/\v"[^"]+"/y w | s/\v\[\w*_\zstest\ze\]/\=matchstr(@w, '\v"\zs[^"]+\ze"')/g

<强>解释

  • \v =&#34;非常神奇&#34;
  • g/\v"[^"]+"使用包含"<some text>"
  • 的行
  • /y w猛烈地注册到reg。 w(而不是使用getline())
  • |再增加一个命令
  • \zs =开始匹配,\ze =结束匹配(比使用预测更快等)。
  • \w与使用[0-9A-Za-z_]
  • 相同
  • \[\w*_\zstest\ze\]&#34;匹配&#34; [<almost any characters>_test],但真正的匹配&#34;由于test\zs
  • ,替换为\ze
  • matchstr(str, match)返回match
  • 中的str
  • matchstr(@w, '\v"\zs[^"]+\ze"')从该行获取""之间的字符(使用reg w
  • ...并使用它来替换匹配的test
  • /g为行
  • 中出现的所有[<almost any characters>_test]执行此操作

答案 1 :(得分:1)

这对你好吗?

%s/\[.\{-}_\zstest\ze\]/\=split(getline('.'), '"')[1]/

这也适用(使用你的例子),并且直截了当:

%s/\[subject_test\]/\="[subject_".split(getline("."),'"')[1]."]"/

答案 2 :(得分:0)

在VimL中,单引号字符串不插入反斜杠,而双引号字符串则执行。

因此,请注意:echo '\':echo "\\"之间的区别。在你的例子中,你使用双引号,因为你没有关闭魔法,你有很多逃避做。见:help magic ...因为我发现了\v,所以人们告诉我,我会更愉快。

答案 3 :(得分:0)

要转义在替代函数中使用的字符,我使用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

例如,您可以使用escape('\([''"]\)\(.\{-}\)\1','\') 这将扩展为:\\(['"]\\)\\(.\\{-}\\)\\1