Sida 1 av 1

Räkna och lista länkar i textfiler [LÖST]

Postat: 15 apr 2009, 18:24
av ubot
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)
.
.
.

Re: Räkna och lista länkar i textfiler

Postat: 15 apr 2009, 23:35
av Osprey
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").

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);
}
Bygg med:

Kod: Markera allt

cc clinks.c -o clinks
Och kör med:

Kod: Markera allt

./clinks files
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... O0

[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.

Re: Räkna och lista länkar i textfiler

Postat: 19 apr 2009, 01:32
av ubot
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").

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);
}
Bygg med:

Kod: Markera allt

cc clinks.c -o clinks
Och kör med:

Kod: Markera allt

./clinks files
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... O0

[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.
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.

Re: Räkna och lista länkar i textfiler

Postat: 19 apr 2009, 03:13
av David Andersson
Pedagogisk upptakt

Du kan använda kommandot uniq, som först kräver att input är sorterat

Kod: Markera allt

sort infil.txt | uniq -c
Sen sorterar vi dess output numeriskt i omvänd ordning

Kod: Markera allt

sort infil.txt | uniq -c | sort -nr
resultat
3 google.com
2 wikipedia.org
1 yahoo.com
1 ubuntu.com
För att få exakt det utformat du frågat om använder vi t.ex awk

Själva svaret

Kod: Markera allt

sort infil.txt | uniq -c | sort -nr | awk '{print $2" ("$1")"}'
google.com (3)
wikipedia.org (2)
yahoo.com (1)
ubuntu.com (1)
Förlåt Osprey, kunde inte heller hålla mej. :)

Re: Räkna och lista länkar i textfiler

Postat: 19 apr 2009, 03:19
av David Andersson
ubot skrev: i flera textfiler
Glömde "flera". Ersätt sort infil.txt i början med sort fil1.txt fil2.txt fil3.txt eller sort fil*.txt.

Om du bara vill se 10-i-topp, lägg till | head -10 i slutet.

Re: Räkna och lista länkar i textfiler

Postat: 19 apr 2009, 11:26
av Osprey
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...?

O0

Re: Räkna och lista länkar i textfiler

Postat: 21 apr 2009, 18:32
av ubot
David Andersson skrev:Pedagogisk upptakt

Du kan använda kommandot uniq, som först kräver att input är sorterat

Kod: Markera allt

sort infil.txt | uniq -c
Sen sorterar vi dess output numeriskt i omvänd ordning

Kod: Markera allt

sort infil.txt | uniq -c | sort -nr
resultat
3 google.com
2 wikipedia.org
1 yahoo.com
1 ubuntu.com
För att få exakt det utformat du frågat om använder vi t.ex awk

Själva svaret

Kod: Markera allt

sort infil.txt | uniq -c | sort -nr | awk '{print $2" ("$1")"}'
google.com (3)
wikipedia.org (2)
yahoo.com (1)
ubuntu.com (1)
Förlåt Osprey, kunde inte heller hålla mej. :)
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!

Re: Räkna och lista länkar i textfiler

Postat: 21 apr 2009, 18:35
av ubot
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...?

O0
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.