如何使用Vim提取正则表达式匹配

时间:2012-01-31 12:33:41

标签: regex vim match text-extraction

样品:

case Foo:
    ...
    break;
case Bar:
    ...
    break;
case More: case Complex:
    ...
    break:
...

我想检索RegEx \(的所有正则表达式匹配(整个匹配文本,甚至更好,\)case \([^:]*\):之间的部分)。喜欢(在一个新的新文件中):

Foo
Bar
More
Complex
...

用例的另一个例子是从HTML文件中提取某些部分,比如图像URL。

是否有一种简单的方法来绘制所有RegEx匹配并将它们放在 Vim 的缓冲区中?

注意:它与extract text using vim类似,但我也有兴趣删除不匹配的行,最好没有庞大或复杂的RegEx。

5 个答案:

答案 0 :(得分:24)

在整个作品中有一种收集模式匹配的一般方法 的文字。该技术利用了替代品 :substitute命令的表达式功能 (见:help sub-replace-\=)。关键的想法是使用替代 枚举所有模式匹配以评估表达式存储 他们没有替代。

首先,让我们考虑保存比赛。为了保持序列 匹配文本片段,使用列表很方便 (见:help List)。但是,无法修改列表 直截了当地,使用:let命令,因为没有办法 在表达式中运行Ex命令(包括\=替换表达式)。 但是,我们可以调用其中一个修改列表的函数。对于 例如,add()函数旨在将给定项附加到 指定列表(见:help add())。

另一个问题是如何在运行时避免文本修改 替代。一种方法是使模式始终具有 通过预先加\ze或向其附加\zs个原子来实现零宽度匹配 (见:help /\zs:help /\ze)。以这种方式修改的模式 捕获在出现之前或之后的空字符串 文本中的原始模式(此类匹配称为零宽度匹配 在Vim;见:help /zero-width)。然后,如果替换文本也是 空的,替换有效地改变了什么:它只是替换 与空字符串的零宽度匹配。

add()函数以及修改列表的大部分内容 函数,返回对已更改列表的引用,用于我们的技术 要工作,我们需要以某种方式从它获得一个空字符串。最简单的 方法是通过指定范围从中提取零长度的子列表 索引使得起始索引大于结束索引。

结合上述想法,我们获得以下Ex命令。

:let t=[] | %s/\<case\s\+\(\w\+\):\zs/\=add(t,submatch(1))[1:0]/g

执行后,累计第一个子组的所有匹配 在变量t引用的列表中,可以按原样使用 以某种方式处理。例如,粘贴列表的内容之一 在插入模式下单独行中的一个,键入

  

控制 + - [R =t 输入

要在普通模式下执行相同操作,只需使用:put命令:

:pu=t

答案 1 :(得分:2)

虽然无法编写单行代码来完成您的示例,但很难以交互方式键入:%s/case \([^:]*\):/\=.../等命令。

我更喜欢使用vim-grex执行以下步骤:

  1. 使用/检查正则表达式是否与预期的行匹配。 例如:/^\s*\<case\s\+\([^:]*\):.*$<Enter>
  2. 执行:Grey。它猛拉与当前搜索模式匹配的行。
  3. :new等打开新缓冲区
  4. p
  5. 放置被拉动的线条
  6. :%s//\1/修剪无趣的部分。

答案 2 :(得分:1)

鉴于“帮助”可能是诸如“ rust”或“ perlang”之类的任何单词,因此如何使用vim regex从以下行中提取单词。

vim:tw=78:ts=8:ft=help:norl:

解决方案:

let foo = substitute(foo, '^\s*vim:.*:ft=\([a-z]\+\).*:\s*$', '\1', '')
echo "foo: '" . foo . "'"

打印:

foo: 'help'

上师冥想:这是怎么回事?

将字符串放入变量foo中,并对其进行匹配以断言行的开头,然后是任意数量的空格,文字vim和文字冒号,然后是任意数量的任何字符由冒号ft=加上任何字母和单词,然后断言该行以冒号结尾。将所有内容扔到名为1的寄存器中,然后将其返回到参数2中,该参数substitute会用之前的字符串替换。

作为一般的哲学,任何比您的手指在屏幕上长的正则表达式都会失败,因此请降低屏幕分辨率直到适合为止。

答案 3 :(得分:0)

:g/^case\s\L\l\+\scase.*/s/case/\r&/g
:let @a=''|g/^case\s\L\l\+:/y A

现在打开一个新的缓冲区或tmp文件,并且aply:

"ap
:%s_^\vcase ([^:]+):_\1_

或者如果您不关心当前缓冲区(当然可以撤消此操作)(已更新以获取复杂示例):

:g/^case\s\L\l\+\scase.*/s/case/\r&/g
:v/^case\s\L\l\+:/d
:%s_^\vcase ([^:]+):_\1_

答案 4 :(得分:0)

仅作为ib。公认答案的一小部分,按原样运作。看来n标志已足够避免不必要的替换问题。

:let t=[] | %s/\<case\s\+\(\w\+\):/\=add(t,submatch(1))/gn

通过s_flag帮助:

[n]报告比赛的次数,不实际替代。 [c] 标志被忽略。报告的匹配情况就好像'report'为零。 对计数项目很有用。 如果使用\= sub-replace-expression,则表达式将为 每次比赛在沙盒中进行评估。