样品:
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。
答案 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执行以下步骤:
/
检查正则表达式是否与预期的行匹配。
例如:/^\s*\<case\s\+\([^:]*\):.*$<Enter>
:Grey
。它猛拉与当前搜索模式匹配的行。:new
等打开新缓冲区p
等:%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
,则表达式将为 每次比赛在沙盒中进行评估。