2010-10-23 23 views
3

我原來問過這個問題:Regular Expression in gVim to Remove Duplicate Domains from a List如何從大量URL中刪除重複域?正則表達式或否則

不過,我意識到我可能會更容易找到工作解決方案,如果我在什麼解決的方法,我願意接受條款「開闊了我的範圍」。

因此,我將改寫我的問題&也許我會得到一個更好的解決方案......這裏有雲:

我有一個.txt文件的URL的大名單(我運行Windows Vista 32位),我需要刪除重複的DOMAINS(以及整個對應的URL到每個副本),同時留下每個域的第一次出現。在這個特定的文件中大約有6,000,000個URL,格式如下(這些URL顯然沒有空格,我只需要這樣做,因爲我沒有足夠的帖子來發布許多「實時」URL ):

http://www.exampleurl.com/something.php 
http://exampleurl.com/somethingelse.htm 
http://exampleurl2.com/another-url 
http://www.exampleurl2.com/a-url.htm 
http://exampleurl2.com/yet-another-url.html 
http://exampleurl.com/ 
http://www.exampleurl3.com/here_is_a_url 
http://www.exampleurl5.com/something

無論該解決方案是,使用上述的輸入輸出文件,應該是這樣的:

http://www.exampleurl.com/something.php 
http://exampleurl2.com/another-url 
http://www.exampleurl3.com/here_is_a_url 
http://www.exampleurl5.com/something

你注意到沒有重複的域名,現在,它留下的第一背後它遇到的情況。

如果有人能幫助我,無論是使用正則表達式還是某些我不知道的程序,那將會很棒。

雖然我會說這個,但除了Windows操作系統之外,我沒有經驗使用其他任何東西,因此需要一個除Windows程序以外的解決方案,可能需要一點「寶貝步」才能說出來(如果有人是善良的足以做到這一點)。

回答

2

正則表達式在Python中,非常原始和不使用子工作。基本的概念是使用字典鍵和值,鍵是域名,如果鍵已經存在,值將被覆蓋。

import re 

pattern = re.compile(r'(http://?)(w*)(\.*)(\w*)(\.)(\w*)') 
urlsFile = open("urlsin.txt", "r") 
outFile = open("outurls.txt", "w") 
urlsDict = {} 

for linein in urlsFile.readlines(): 
    match = pattern.search(linein) 
    url = match.groups() 
    domain = url[3] 
    urlsDict[domain] = linein 

outFile.write("".join(urlsDict.values())) 

urlsFile.close() 
outFile.close() 

你可以擴展它來過濾子域,但基本思想是在那裏我想。對於6百萬個網址,在Python中可能需要相當長一段時間...

有些人,當與 面臨的問題,認爲「我知道,我將使用 正則表達式。」現在他們有 兩個問題。 --Jamie Zawinski, comp.emacs.xemacs

1

對於這種特殊情況,我不會使用正則表達式。 URL是一個明確定義的格式,在BCL中有一種易於使用的格式解析器:Uri類型。它可以用來輕鬆解析類型並獲取您尋求的域信息。

下面是一個簡單的例子

public List<string> GetUrlWithUniqueDomain(string file) { 
    using (var reader = new StreamReader(file)) { 
    var list = new List<string>(); 
    var found = new HashSet<string>(); 
    var line = reader.ReadLine(); 
    while (line != null) { 
     Uri uri; 
     if (Uri.TryCreate(line, UriKind.Absolute, out uri) && found.Add(uri.Host)) { 
     list.Add(line); 
     } 
     line = reader.ReadLine(); 
    } 
    } 
    return list; 
} 
0
  1. 查找在UNIX系統中,如果你沒有一個,或得到的cygwin
  2. 使用TR轉換 ''爲了方便TAB。
  3. 使用排序(1)按域名部分對行進行排序。通過編寫一個awk程序來標準化www部分,這可能會變得更容易一些。

和çava,你有dups在一起。也許可以使用uniq(1)查找dublicates。

(附加題:爲什麼不能單獨一個正則表達式做這個計算機專業的學生應該考慮抽水引理。)

1

我會使用Perl和regexps的組合。我的第一個版本我

use warnings ; 
    use strict ; 
    my %seen ; 
    while (<>) { 
     if (m{ // (.*?)/}x) { 
     my $dom = $1 ; 

     print unless $seen {$dom} ++ ; 
     print "$dom\n" ; 
    } else { 
     print "Unrecognised line: $_" ; 
    } 
    } 

但是,這將www.exampleurl.com和exampleurl.com視爲不同。 我的第二個版本有

if (m{ // (?:www\.)? (.*?)/}x) 

忽略「www」。在前面。 你或許可以細化一下正則表達式,但這是留給讀者的。

最後你可以評論一下正則表達式(/x限定符允許這個)。這取決於誰將閱讀它 - 它可能被認爲是過於冗長。

  if (m{ 
       //   # match double slash 
       (?:www\.)? # ignore www 
       (   # start capture 
        .*?  # anything but not greedy 
       )   # end capture 
       /  # match/
       }x) { 

我用m{}而不是//避免/\/\/