在Vim中使用正向回顾断言和替换?

12

我想使用Vim来匹配正则表达式并进行替换。我有一个包含以下内容的tsv文件:

rs11223-A        -A
rs23300-G        -TTA
rs9733-T          -G
rs11900000-GT    -TTG

我希望您能将破折号(-)替换为制表符,只在rs后的第一列中进行替换...
在Vim中,我试图使用以下命令进行替换:
:%s/(?<=^rs[0-9]{1,12})-/\t/g   

有人能指出我的问题并给出正确的解决方案吗?

4个回答

21

可能会受到配置的影响,在我的环境中,我必须在{ , }前面加上\

此外,Vim有\zs\ze来开始和结束匹配,因此通常不需要处理普通的正则表达式lookaround。

这样做可以实现您想要的效果:

:%s/^rs\d\{1,12}\zs-/\t/g

8

正向预测需要使用:

\@<=

所以你可以使用类似以下的内容:
:%s/\d\@<=-/\t/g

您的实际数据可能更加复杂,但是根据您提供的内容,您也可以采用以下方式解决:
:%s/-/\t

如果rs应该在行首出现,您可以使用\zs来指定匹配的开始,并使用锚定(^):
:%s/^rs\d*\zs-/\t

#2 应该是::%s/^rs\d@<=-/\t/g - KomodoDave
@KomodoDave:你的模式将匹配行首的 rs,紧接着是一个破折号(-),前面是一个单个数字(正向零宽断言\d\@<=-)。给定数据中的任何一行都不符合该模式。如果您坚持使用锚定,可以使用我刚添加的模式。 - heijp06
我以为 OP 指的是字符列中的列,但也许他并不是。我复制了你的编辑,并没有将 \d 替换为 -,而我的本意是写成::%s/^rs-@<=/\t/g,它匹配以行首的 'rs' 后第一个字符列中的 '-'。 - KomodoDave

0

使用回顾后发表达式的正确方式是:

%s/\(\d\+\)\@<=-/\t/gc 

\(\d\+\)\@<= 的意思是向后查找,以找到数字(\d\+ 表示至少找到一个数字)。根据这里所述,我们必须在应用正向查找之前捕获 \d\+,因此在 \d\+ 周围加上了 \(\)

另外,在vim中使用普通的正则表达式量词符号 + 时,我们必须对它进行转义(\+),请参见这里的文档


0
你想要以下内容:
%s/^\(rs[0-9]\{1,12\}\)-/\1\t/g

Vim正则表达式需要一些特殊的转义字符来处理 {}()

同时,在替换部分,你需要使用 \1 来插入匹配到的字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接