【问题标题】:Regular Expression in gVim to Remove Duplicate Domains from a ListgVim 中的正则表达式从列表中删除重复域
【发布时间】:2011-04-29 11:06:34
【问题描述】:

我需要一个在 gVim 中使用的正则表达式,它将从 URL 列表中删除重复的域(gVim 可以在此处下载:http://www.vim.org/download.php

我在一个 .txt 文件中有超过 6,000,000 个 URL 的列表(在 gVim 中打开以进行编辑)。

网址采用以下格式:

http://www.example.com/some-url.php
http://example2.com/another_url.html
http://example3.com/
http://www.example4.com/anotherURL.htm
http://www.example.com/some-url2.htm
http://example.com/some-url3.html
http://www.example2.com/somethingelse.php
http://example5.com

换句话说,URL 没有特定的格式。有些有 WWW,有些没有,它们都有不同的格式。

我需要一个为 gVim 编写的正则表达式,它将从列表中删除所有重复的 DOMAIN(以及相应的 URL),留下它找到的第一个实例。

因此它将采用上面发布的示例列表,最终结果应如下所示:

http://www.example.com/some-url.php
http://example2.com/another_url.html
http://example3.com/
http://www.example4.com/anotherURL.htm
http://example5.com

这里有两个很好的网站,它们很好地解释了如何在 gVim 中使用正则表达式:

http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/gvim/gvim.html#Vi-Regular-Expressions

http://www.softpanorama.org/Editors/Vimorama/vim_regular_expressions.shtml

【问题讨论】:

  • 你能告诉我们一些你迄今为止尝试过的例子吗?查找/删除我发现的重复项的一个技巧是首先对列表进行排序。这是一个巨大的文件,所以这对您来说可能是一个困难的选择,但它也可能使您的正则表达式更加简单。
  • gVim 实际上有一个非常好的内置功能,用于对 URL 进行排序,所以这完全没有问题。我只需键入以下内容并按回车:sort u 按字母顺序对所有行进行排序,然后删除重复的 LINES(不是域)。至于展示一些例子,我还没有走得太远。这是一个(我实际上是从这个站点得到的,但 gVim 说它不是一个公认的命令或正则表达式)stackoverflow.com/questions/2280666/…
  • 根据 gvim 的文档,输入您要执行的操作的格式应该是这种格式: :start_point,end_points/search_pattern/replacement_pattern/g 这个 URL 给出了一些简单的例子 147.188.192.43/documentation/tutorials/docsystem/build/… ...但是我对正则表达式的了解一无所有...直到今天,我什至没有听说过。

标签: windows regex vim


【解决方案1】:

如果你想使用正则表达式,你可以尝试调整以下:%s!\v%(^http://%(www\.)?(%([^./]+\.)+[^./]+)%(/.*)?$\_.{-})@<=^http://%(www\.)?\1%(/.*)?\n!!g,但是在 60 亿个 url 上会非常很慢,并且不适用于未知数原因。这是一个更好的方法:

:let g:gotDomains={}
:%g/^/let curDomain=matchstr(getline('.'), '\v^http://%(www\.)?\zs[^/]+') | if !has_key(g:gotDomains, curDomain) | let g:gotDomains[curDomain]=1 | else | delete _ | endif

它正在执行以下操作:

  1. let g:gotDomains={} 创建一个空字典,我们将在其中保存所有域
  2. %g/^/{command} 在每一行执行{command}
  3. let curDomain=matchstr(...)获取域名

    1. getline('.') 来自当前行
    2. \v 允许我省略在正则表达式中写很多反斜杠(非常神奇)
    3. ^ 从字符串开始
    4. \zs 从这里开始匹配(省略捕获\zs 之前的所有内容)
  4. if !has_key(g:gotDomains, curDomain) 如果之前没有出现过域。

  5. let g:gotDomains[curDomain]=1 然后将其添加到已知域列表中(我们这里不需要1,我使用字典只是为了更快地访问)。
  6. delete _ 否则删除 黑洞 寄存器的行(这意味着,不要将其内容保存在任何寄存器中)。

【讨论】:

  • 哇!您提供的第二个解决方案(然后清楚地解释了为什么它是一个解决方案)效果很好!非常感谢 ZyX!我花了很多时间寻找一个解决方案,而且那是正确的。我真的很感谢您花时间不仅提供解决方案,而且解释它......嗯,这真的很有帮助。再次感谢!
  • @Robert:这个地方真是难以置信。人们用很多有见地的答案帮助我们度过了他们的时间。试着总是在这里给人们投票,然后谢谢。我非常感谢我在这里得到的答案!
【解决方案2】:

试试这个:

%! sort | uniq

【讨论】:

  • 老实说,我什至不确定如何尝试,哈哈。不过,我感谢您的帮助!
猜你喜欢
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 2012-07-05
  • 1970-01-01
相关资源
最近更新 更多