Räkna och lista länkar i textfiler [LÖST]
Räkna och lista länkar i textfiler [LÖST]
Jag behöver ett kommando eller script som gör det möjligt att lägga ihop textfiler till en enda stor textfil och sedan räkna antal gånger som länkar till samma destination förekommer i filen. Jag vill alltså skapa en "topplista" sorterad efter hur många gånger varje länk förekommer i flera textfiler (som gärna får slås ihop till en enda stor fil). Jag vill räkna och sortera länkar efter hur ofta länkarna förekommer i en textfil. Typ så här:
google.com
yahoo.com
ubuntu.com
wikipedia.org
google.com
google.com
wikipedia.org
blir då:
google.com (3)
wikipedia.org (2)
yahoo.com (1)
.
.
.
google.com
yahoo.com
ubuntu.com
wikipedia.org
google.com
google.com
wikipedia.org
blir då:
google.com (3)
wikipedia.org (2)
yahoo.com (1)
.
.
.
Senast redigerad av 1 ubot, redigerad totalt 25 gånger.
- Osprey
- Inlägg: 6310
- Blev medlem: 06 apr 2008, 00:09
- OS: Ubuntu
- Ort: Göteborg/Mölndal/Falkenberg
- Kontakt:
Re: Räkna och lista länkar i textfiler
Kunde inte hålla mig utan hackade ihop ett litet C-program, orkade inte trassla med awk och bash... Det är lite "quick 'n dirty" med shell-kommandon via system(), men det funkar... 
Kopiera och spara i t.ex "clinks.c" (för "Count links").
Bygg med:
Och kör med:
Efter som det är ett snabbhack så är parameterhanteringen rätt enkel, det klarar av en enda fil, eller flera filer med wildcard. Om du vill ange wildcard måste du ha en backslash innan, t.ex "clinks \*.html", eller "clinks a\*.html"...
Jag har testat det och det funkar fint för både http- och https-länkar etc. plus lite annat när det gäller olika syntax för samma länk, men det kan finnas buggar kvar...
Testa, ändra och fixa så att det blir som du vill ha det...
[Edit] Givetvis kan du kopiera det kompilerade programmet till /bin, /usr/bin, /usr/local/bin eller vad du nu vill så att du kan köra det som ett kommando.

Kopiera och spara i t.ex "clinks.c" (för "Count links").
Kod: Markera allt
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
main(int argc,char *argv[])
{
int i,j;
char buf[255],buf2[255],cmd[255],*_ptr,*_ptr2;
FILE *_fp,*_fp2;
extern char *strcasestr (__const char *__haystack, __const char *__needle);
sprintf(cmd,"cat %s > alla_filer",argv[1]);
system(cmd);
if ((_fp=fopen("alla_filer","r")) == NULL){
perror("Failed to open file-listing");
exit(errno);
}
if ((_fp2=fopen("alla_filer2","w")) == NULL){
perror("Failed to open sort-file");
exit(errno);
}
while (fgets(buf,sizeof(buf),_fp) != NULL){
if(strlen(buf)>0){
if ((_ptr=strcasestr(buf,"href")) != NULL){
if ((_ptr=strcasestr(buf,"https")) != NULL){
j=8;
}else{
j=7;
_ptr=strcasestr(buf,"http");
}
if (_ptr != NULL){
_ptr+=j;
if ((_ptr2=strcasestr(_ptr,">")) != NULL){
*_ptr2=0;
if ((_ptr2=strcasestr(_ptr,"\"")) != NULL){
*_ptr2=0;
}
_ptr2--;
if (*_ptr2=='/'){
*_ptr2=0;
}
fprintf(_fp2,"%s\n",_ptr);
/*
while(*_ptr){
printf("%c",*_ptr);
_ptr++;
}
*/
/* printf("\n"); */
}
}
}
}
}
fclose(_fp);
fclose(_fp2);
sprintf(cmd,"sort alla_filer2 > alla_filer3");
system(cmd);
if ((_fp=fopen("alla_filer3","r")) == NULL){
perror("Failed to open sorted file-listing");
exit(errno);
}
if ((_fp2=fopen("alla_filer4","w")) == NULL){
perror("Failed to open result file");
exit(errno);
}
i=0; buf2[0]=0;
while (fgets(buf,sizeof(buf),_fp) != NULL){
i++;
if ((strcmp(buf,buf2)!=0)&&(strlen(buf2)!=0)){
fprintf(_fp2,"%04d,%s",i,buf2);
j=i;
i=0;
}
strcpy(buf2,buf);
}
fprintf(_fp2,"%04d,%s",j,buf2);
fclose(_fp);
fclose(_fp2);
sprintf(cmd,"sort -rf alla_filer4 > alla_filer5");
sprintf(cmd,"sort -rnk1 alla_filer4 > alla_filer5");
sprintf(cmd,"sort -t, -k1,4rn -k2 alla_filer4 | sed -e 's/,/ /g' > alla_filer5");
system(cmd);
if ((_fp=fopen("alla_filer5","r")) == NULL){
perror("Failed to open sorted result file");
exit(errno);
}
/*
if ((_fp2=fopen("alla_filer6","w")) == NULL){
perror("Failed to open formatted result file");
exit(errno);
}
*/
while (fgets(buf,sizeof(buf),_fp) != NULL){
_ptr=buf;
while(*_ptr=='0'){
*_ptr=0x020;
_ptr++;
}
printf("%s",buf);
}
fclose(_fp);
sprintf(cmd,"rm alla_filer alla_filer2 alla_filer3 alla_filer4 alla_filer5");
system(cmd);
}
Kod: Markera allt
cc clinks.c -o clinks
Kod: Markera allt
./clinks files
Jag har testat det och det funkar fint för både http- och https-länkar etc. plus lite annat när det gäller olika syntax för samma länk, men det kan finnas buggar kvar...
Testa, ändra och fixa så att det blir som du vill ha det...

[Edit] Givetvis kan du kopiera det kompilerade programmet till /bin, /usr/bin, /usr/local/bin eller vad du nu vill så att du kan köra det som ett kommando.
Agera genom att ta och behålla initiativet, ta de risker detta kräver...
http://www.enargo.com/it/
OpenVMS Shark - i Linux finns inte SYS$CMKRNL...
http://www.enargo.com/it/
OpenVMS Shark - i Linux finns inte SYS$CMKRNL...
Re: Räkna och lista länkar i textfiler
Ah, tack! Jag trodde inte att det skulle behövas så här mycket kod, hehe. Trodde att det fanns några enkla bash-kommandon för att fixa en sådan sak. Tack för att du tog dig tid och fixade scriptet. Jag ska testa det framöver och återkommer med en kommentar när jag har testkört programmet ett par ggr.Osprey skrev:Kunde inte hålla mig utan hackade ihop ett litet C-program, orkade inte trassla med awk och bash... Det är lite "quick 'n dirty" med shell-kommandon via system(), men det funkar...
Kopiera och spara i t.ex "clinks.c" (för "Count links").Bygg med:Kod: Markera allt
#define __USE_GNU #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> main(int argc,char *argv[]) { int i,j; char buf[255],buf2[255],cmd[255],*_ptr,*_ptr2; FILE *_fp,*_fp2; extern char *strcasestr (__const char *__haystack, __const char *__needle); sprintf(cmd,"cat %s > alla_filer",argv[1]); system(cmd); if ((_fp=fopen("alla_filer","r")) == NULL){ perror("Failed to open file-listing"); exit(errno); } if ((_fp2=fopen("alla_filer2","w")) == NULL){ perror("Failed to open sort-file"); exit(errno); } while (fgets(buf,sizeof(buf),_fp) != NULL){ if(strlen(buf)>0){ if ((_ptr=strcasestr(buf,"href")) != NULL){ if ((_ptr=strcasestr(buf,"https")) != NULL){ j=8; }else{ j=7; _ptr=strcasestr(buf,"http"); } if (_ptr != NULL){ _ptr+=j; if ((_ptr2=strcasestr(_ptr,">")) != NULL){ *_ptr2=0; if ((_ptr2=strcasestr(_ptr,"\"")) != NULL){ *_ptr2=0; } _ptr2--; if (*_ptr2=='/'){ *_ptr2=0; } fprintf(_fp2,"%s\n",_ptr); /* while(*_ptr){ printf("%c",*_ptr); _ptr++; } */ /* printf("\n"); */ } } } } } fclose(_fp); fclose(_fp2); sprintf(cmd,"sort alla_filer2 > alla_filer3"); system(cmd); if ((_fp=fopen("alla_filer3","r")) == NULL){ perror("Failed to open sorted file-listing"); exit(errno); } if ((_fp2=fopen("alla_filer4","w")) == NULL){ perror("Failed to open result file"); exit(errno); } i=0; buf2[0]=0; while (fgets(buf,sizeof(buf),_fp) != NULL){ i++; if ((strcmp(buf,buf2)!=0)&&(strlen(buf2)!=0)){ fprintf(_fp2,"%04d,%s",i,buf2); j=i; i=0; } strcpy(buf2,buf); } fprintf(_fp2,"%04d,%s",j,buf2); fclose(_fp); fclose(_fp2); sprintf(cmd,"sort -rf alla_filer4 > alla_filer5"); sprintf(cmd,"sort -rnk1 alla_filer4 > alla_filer5"); sprintf(cmd,"sort -t, -k1,4rn -k2 alla_filer4 | sed -e 's/,/ /g' > alla_filer5"); system(cmd); if ((_fp=fopen("alla_filer5","r")) == NULL){ perror("Failed to open sorted result file"); exit(errno); } /* if ((_fp2=fopen("alla_filer6","w")) == NULL){ perror("Failed to open formatted result file"); exit(errno); } */ while (fgets(buf,sizeof(buf),_fp) != NULL){ _ptr=buf; while(*_ptr=='0'){ *_ptr=0x020; _ptr++; } printf("%s",buf); } fclose(_fp); sprintf(cmd,"rm alla_filer alla_filer2 alla_filer3 alla_filer4 alla_filer5"); system(cmd); }
Och kör med:Kod: Markera allt
cc clinks.c -o clinks
Efter som det är ett snabbhack så är parameterhanteringen rätt enkel, det klarar av en enda fil, eller flera filer med wildcard. Om du vill ange wildcard måste du ha en backslash innan, t.ex "clinks \*.html", eller "clinks a\*.html"...Kod: Markera allt
./clinks files
Jag har testat det och det funkar fint för både http- och https-länkar etc. plus lite annat när det gäller olika syntax för samma länk, men det kan finnas buggar kvar...
Testa, ändra och fixa så att det blir som du vill ha det...
[Edit] Givetvis kan du kopiera det kompilerade programmet till /bin, /usr/bin, /usr/local/bin eller vad du nu vill så att du kan köra det som ett kommando.
-
- Inlägg: 1269
- Blev medlem: 15 dec 2007, 03:20
- OS: Xubuntu
Re: Räkna och lista länkar i textfiler
Pedagogisk upptakt
Du kan använda kommandot uniq, som först kräver att input är sorterat
Sen sorterar vi dess output numeriskt i omvänd ordning
resultat
Själva svaret

Du kan använda kommandot uniq, som först kräver att input är sorterat
Kod: Markera allt
sort infil.txt | uniq -c
Kod: Markera allt
sort infil.txt | uniq -c | sort -nr
För att få exakt det utformat du frågat om använder vi t.ex awk3 google.com
2 wikipedia.org
1 yahoo.com
1 ubuntu.com
Själva svaret
Kod: Markera allt
sort infil.txt | uniq -c | sort -nr | awk '{print $2" ("$1")"}'
Förlåt Osprey, kunde inte heller hålla mej.google.com (3)
wikipedia.org (2)
yahoo.com (1)
ubuntu.com (1)

-
- Inlägg: 1269
- Blev medlem: 15 dec 2007, 03:20
- OS: Xubuntu
Re: Räkna och lista länkar i textfiler
Glömde "flera". Ersätt sort infil.txt i början med sort fil1.txt fil2.txt fil3.txt eller sort fil*.txt.ubot skrev: i flera textfiler
Om du bara vill se 10-i-topp, lägg till | head -10 i slutet.
- Osprey
- Inlägg: 6310
- Blev medlem: 06 apr 2008, 00:09
- OS: Ubuntu
- Ort: Göteborg/Mölndal/Falkenberg
- Kontakt:
Re: Räkna och lista länkar i textfiler
Aha, ok! Kanske jag som inte riktigt hängt med och siktat över målet...
Skillnaden är den att mitt program läser in ett antal html-filer och plockar ut länkarna ur dem först. Jag antog att det var så som det var meningen... Men om det bara är att räkna länkar i en färdig fil som bara innehåller ett antal adresser så blir det förstås mycket lättare och då funkar David Anderssons kommandon mycket bättre...
Så valet av lösning beror nog på hur det ska fungera, har du en fil med färdiga adresser i, eller vill du att programmet ska plocka ut länkar ur ett antal html-filer och sammanställa dem till en lista som den sorterar...?


Skillnaden är den att mitt program läser in ett antal html-filer och plockar ut länkarna ur dem först. Jag antog att det var så som det var meningen... Men om det bara är att räkna länkar i en färdig fil som bara innehåller ett antal adresser så blir det förstås mycket lättare och då funkar David Anderssons kommandon mycket bättre...
Så valet av lösning beror nog på hur det ska fungera, har du en fil med färdiga adresser i, eller vill du att programmet ska plocka ut länkar ur ett antal html-filer och sammanställa dem till en lista som den sorterar...?

Agera genom att ta och behålla initiativet, ta de risker detta kräver...
http://www.enargo.com/it/
OpenVMS Shark - i Linux finns inte SYS$CMKRNL...
http://www.enargo.com/it/
OpenVMS Shark - i Linux finns inte SYS$CMKRNL...
Re: Räkna och lista länkar i textfiler
Ah, lysande! Det var precis något sådant här jag hade i tankarna när jag postade min fråga i tråden. Tack!David Andersson skrev:Pedagogisk upptakt
Du kan använda kommandot uniq, som först kräver att input är sorterat
Sen sorterar vi dess output numeriskt i omvänd ordningKod: Markera allt
sort infil.txt | uniq -c
resultatKod: Markera allt
sort infil.txt | uniq -c | sort -nr
För att få exakt det utformat du frågat om använder vi t.ex awk3 google.com
2 wikipedia.org
1 yahoo.com
1 ubuntu.com
Själva svaret
Kod: Markera allt
sort infil.txt | uniq -c | sort -nr | awk '{print $2" ("$1")"}'
Förlåt Osprey, kunde inte heller hålla mej.google.com (3)
wikipedia.org (2)
yahoo.com (1)
ubuntu.com (1)
Re: Räkna och lista länkar i textfiler
Nej, jag har flera olika textfiler med bara länkar i, en länk på varje rad. Jag ville sortera alla länkarna efter antal ggr dom finns med i textfilen/textfilerna. Det får jag lättast på det andra sättet. Förlåt om jag var otydlig, men nu har jag iofs sett hur ett program plockar ut länkar från html-filer.Osprey skrev:Aha, ok! Kanske jag som inte riktigt hängt med och siktat över målet...![]()
Skillnaden är den att mitt program läser in ett antal html-filer och plockar ut länkarna ur dem först. Jag antog att det var så som det var meningen... Men om det bara är att räkna länkar i en färdig fil som bara innehåller ett antal adresser så blir det förstås mycket lättare och då funkar David Anderssons kommandon mycket bättre...
Så valet av lösning beror nog på hur det ska fungera, har du en fil med färdiga adresser i, eller vill du att programmet ska plocka ut länkar ur ett antal html-filer och sammanställa dem till en lista som den sorterar...?