3

私は最初にこの質問をしました:リストから重複ドメインを削除するための gVim の正規表現

ただし、どのソリューションを受け入れるかという点で「範囲を広げる」と、有効なソリューションが見つかる可能性が高くなる可能性があることに気付きました。

だから、私は私の質問を言い換えると、多分私はより良い解決策を得るでしょう...ここに行きます:

.txt ファイルに多数の URL のリストがあり (Windows Vista 32 ビットを実行しています)、重複するドメイン (および各重複に対応する 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 OS以外を使用した経験がないので、Windowsプログラム以外のものを伴うソリューションは、いわば少しの「ベビーステップ」が必要です(誰かがそうするのに十分親切であれば) )。

4

5 に答える 5

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()

サブドメインを除外するように拡張できますが、基本的な考え方はそこにあると思います。また、600 万の URL の場合、Python ではかなり時間がかかる場合があります...

問題に直面したときに、「分かった、正規表現を使用する」と考える人もいます。現在、彼らには 2 つの問題があります。--- comp.emacs.xemacs のジェイミー・ザウィンスキー

于 2010-10-23T07:47:12.937 に答える
1

Perlと正規表現を組み合わせて使用​​します。私の最初のバージョンi

   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を異なるものとして扱います。私の2番目のバージョンは

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{}のではなく使う///\/\/

于 2010-10-23T11:12:32.777 に答える
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;
}
于 2010-10-23T04:51:03.083 に答える
0
  1. Unixボックスがない場合は見つけるか、cygwinを入手してください
  2. tr を使用して '.' を変換します。便利なように TAB に移動します。
  3. ドメイン名の部分で行をソートするには、sort(1) を使用します。これは、www 部分を正規化する awk プログラムを作成することで、少し簡単になる可能性があります。

そして、あなたは一緒にダップを持っています。おそらくuniq(1)を使用して、重複を見つけます。

(追加のクレジット: 正規表現だけでこれを行うことができないのはなぜですか? コンピューター サイエンスの学生は、ポンピングの補題について考えるべきです。)

于 2010-10-23T04:51:07.660 に答える