0

如何转义正则表达式\([''"]\)\(.\{-}\)\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

4 回答 4

2

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

使用该功能substitute()时,除了使用 eg 时,还有其他模式规则:s///
看到这个::h 替代()
其中的一些部分:

...
但是与 {pat} 的匹配总是像设置了 'magic' 选项并且 'cpoptions' 为空(使脚本可移植)一样。'ignorecase' 仍然是相关的。不使用'smartcase'。
...
请注意,{sub} 中的某些代码具有特殊含义|sub-replace-special|。例如,要将某些内容替换为“\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")

棘手的部分是,在函数替代()中,您将模式用作字符串,这不是在例如命令行中通常使用模式时的情况:s///


编辑(再次由于 OP 的评论):
不能说我理解你的例子的使用,但我忍不住尝试用你问题中的 ex 命令修复它(我正在尝试同时了解VIM)。这是一个有效的命令,并给出了你想要的结果,但同样,我不明白它的用途是什么。
但似乎问题真的是要学习如何在字符串中转义正则表达式。
如果“字符串”总是在要替换的内容之前(并且test每个“”只替换一个):

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

解释

  • \zs=开始比赛,\v=使用“非常神奇”
  • "([^"]+)"“匹配”除"(最少 1 个)和之间"的所有字符( "
    “真正的匹配”尚未开始,但括号中的匹配将作为子匹配编号 1)
  • .*直到下一个表达式的所有字符:
  • _\zstest"match" _test,但\zs在此之后开始“真正的匹配”,所以只有test那个会被替换。
  • /\1/替换为子匹配号 1

已更改这不是“安全的”,我添加了一些更长的匹配项(来自@Kent的回答),并确保仅处理了已"<any characters>"处理的行。
如果“字符串”可以在替换之前或之后

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

解释

  • \v=“非常神奇”
  • g/\v"[^"]+"使用具有"<some text>"
  • /y w将线路拉到 reg。w(而不是使用 getline())
  • |再有一个命令
  • \zs= 开始匹配,\ze= 结束匹配(比使用前瞻等更快)
  • \w与使用相同[0-9A-Za-z_]
  • \[\w*_\zstest\ze\]"match" [<almost any characters>_test],但要替换的“真正匹配”是test因为\zsand\ze
  • matchstr(str, match)返回matchinstr
  • matchstr(@w, '\v"\zs[^"]+\ze"')获取行间""行间的字符(使用 reg w
  • ...并用它来替换匹配的test
  • /g[<almost any characters>_test]为该行中所有出现的
于 2013-02-17T15:44:55.163 回答
1

你可以吗?

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

这也有效(以您的示例为例),并且简单明了:

%s/\[subject_test\]/\="[subject_".split(getline("."),'"')[1]."]"/
于 2013-02-17T10:54:56.230 回答
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

于 2013-02-17T18:44:12.357 回答
0

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

:echo '\'因此,请注意和之间的区别:echo "\\"。在您的示例中,您使用了双引号,并且由于您没有关闭魔法,因此您有很多转义要做。看:help magic......自从我发现了\v,人们告诉我,我在身边更愉快。

于 2013-02-17T17:05:09.693 回答