Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何使用Vim提取文件中的所有正则表达式匹配项?_Regex_Vim_Match_Text Extraction - Fatal编程技术网

Regex 如何使用Vim提取文件中的所有正则表达式匹配项?

Regex 如何使用Vim提取文件中的所有正则表达式匹配项?,regex,vim,match,text-extraction,Regex,Vim,Match,Text Extraction,考虑以下示例: case Foo: ... break; case Bar: ... break; case More: case Complex: ... break: ... 比方说,我们想要检索正则表达式的所有正则表达式匹配项(整个匹配文本,或者更好的是,正则表达式的\(和\))case\([^::*\):,这应该给我们(最好是在一个新的缓冲区中)类似的信息: Foo Bar More Complex ... 另一个用例示例是从HTML文

考虑以下示例:

case Foo:
    ...
    break;
case Bar:
    ...
    break;
case More: case Complex:
    ...
    break:
...
比方说,我们想要检索正则表达式的所有正则表达式匹配项(整个匹配文本,或者更好的是,正则表达式的
\(
\)
)case\([^::*\):,这应该给我们(最好是在一个新的缓冲区中)类似的信息:

Foo
Bar
More
Complex
...
另一个用例示例是从HTML文件中提取一些部分,例如图像的URL

有没有一种简单的方法来绘制所有正则表达式匹配并将它们放在Vim的缓冲区中

注意:它类似于问题“”。然而,与该问题中的设置不同,我还对删除不匹配的行感兴趣,最好不要使用大型或复杂的正则表达式

:g/^case\s\L\l\+\scase.*/s/case/\r&/g
:let @a=''|g/^case\s\L\l\+:/y A
现在打开一个新的缓冲区或tmp文件,然后:

"ap
:%s_^\vcase ([^:]+):_\1_
或者,如果您不关心当前缓冲区(当然可以撤消此操作)(针对复杂示例进行了更新):


在一件作品中,有一种收集图案匹配的通用方法 文本的格式。这项技术利用了具有
:substitute
命令的表达式功能 (请参见
:帮助子替换-\=
)。关键的想法是使用替换 枚举所有模式匹配以计算表达式存储 他们不需要更换

首先,让我们考虑保存火柴。为了保持顺序 对于匹配的文本片段,可以方便地使用列表 (请参见帮助列表)。但是,无法修改列表 直接使用
:let
命令,因为无法 在表达式中运行Ex命令(包括
\=
替换表达式)。 然而,我们可以调用其中一个函数来修改列表。对于 例如,
add()
函数用于将给定项附加到 指定的列表(请参见帮助添加())

另一个问题是如何在运行时避免文本修改 替代品。一种方法是使模式始终具有 通过预加
\ze
或在其上附加
\zs
原子进行零宽度匹配 (请参见
:help/\zs
:help/\ze
)。图案以这种方式修改 捕获事件发生之前或之后的空字符串 文本中的原始模式(此类匹配称为零宽度匹配 在Vim中;请参见
:帮助/zero width
)。然后,如果替换文本也是 空的,替代实际上什么都没有改变:它只是替换 具有空字符串的零宽度匹配

由于
add()
函数以及大多数列表 函数,返回对已更改列表的引用,用于我们的技术 为了工作,我们需要从中获得一个空字符串。最简单的 方法是通过指定一个范围从中提取一个长度为零的子列表 指开始索引大于结束索引的索引

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

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

虽然不可能编写一行代码来完成示例,但很难以交互方式键入命令,例如
:%s/case\([^::]*\):/\=…/

我更喜欢使用以下步骤:

  • 使用
    /
    检查正则表达式是否与预期行匹配。
    例如:
    /^\s*\如何使用vim regex从以下行中提取单词,因为“help”可能是任何类似“rust”或“perlang”的单词。

    vim:tw=78:ts=8:ft=help:norl:
    
    解决方案:

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

    let foo = substitute(foo, '^\s*vim:.*:ft=\([a-z]\+\).*:\s*$', '\1', '')
    echo "foo: '" . foo . "'"
    
    foo: 'help'
    
    大师冥想:这里发生了什么事?

    取变量
    foo
    中的字符串,并将其匹配以断言行的开头,然后是任意数量的空格、文字
    vim
    和文字冒号,然后是任意数量的字符,后跟冒号
    ft=
    和任何带字母的单词,然后是任意字符,并断言行以冒号结尾。将所有这些内容放入名为1的寄存器中,然后将其返回到参数2中,
    substitute
    接受并用替换前面的字符串


    一般来说,屏幕上任何长度超过手指的正则表达式都是一个巨大的失败,因此请降低屏幕分辨率,直到它合适为止。

    作为ib公认答案的一个小补充,它也可以正常工作。似乎标志
    n
    足以避免不必要的替换问题

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

    :让t=[]|%s/\你是指反向引用吗
    :%s/^\vcase([^::]+):/\1/
    使用
    \1
    获取第一个捕获组。如果您只想将这些组提取到一个新文件中(您的问题不清楚),您可以使用sed或grep更轻松地执行此操作;sed示例:
    sed-n'/^\s*case\s\+/{s/\s*case\s\+\([^::\+\):/\1/;p}文件
    @beerbajay:在新文件中可以。我同意sed会做得很好,只是我需要启动一个命令提示符并再次找到文件,所以我正在寻找一个Vim解决方案。@mathematic.coffee:一点也不。问题不是搜索和替换(除非包含新行),而是抓取所有匹配项并将它们放入另一个缓冲区。这与此问题非常相似:在第一个截取的代码中列出的命令中肯定存在一些错误。您在发布之前运行过它们吗?这两个命令都不会运行!您可能的意思是
    :let@a=''g/^case\s\L\L+:/y A
    :v/../d
    :g!//d
    是一个很好的技巧,因此它会删除所有不匹配的行。然而,它并不是真正严格的正则表达式匹配。它提取匹配行,然后假设每行有一个匹配项,第二次搜索和替换将起作用。这在一般情况下是行不通的。我会更新我的样本。@ib。谢谢你指出,你说得对。当我在windows上,在excel前面时会发生这种情况。。。更新答案。@Wernight,好的,我已经为你的特殊情况更新了我的答案。回答得好。我特别喜欢这个小男孩