ubuntuusers.de

TOP5 aus einfacher Textliste greppen

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

cryptosteve

Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

Moin, ich möchte aus einer simplen Textliste eine TOP5-Liste (nach Anzahl der Vorkommnisse) greppen, kriegs aber nicht so recht gebacken. Eine Listenzeile ist immer wie folgt aufgebaut: Zeit Host Datei, z.B. 1208101519 localhost index.html. Das Logfile sieht beispielhaft wie folgt aus:

1208101519 localhost index.html
1208101519 localhost index.html
1208101519 host1 index.php
1208101519 host2 index1.html
1208101519 host1 index2.html
1208101519 host5 index1.html
1208101519 host4 index.php
1208101519 host3 index1.html
1208101519 host3 index1.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html

Ich möchte jetzt jeweils die ersten fünf (oder hier hilfsweise drei) häufigsten Vorkommen der Spalte 'host' und 'datei' haben.

Jemand eine Idee dazu?

Edit: Code-Block korrigiert

uname

Anmeldungsdatum:
28. März 2007

Beiträge: 6030

Wohnort: 127.0.0.1

Das suche ich auch noch, vor allem addiert über viele Zeilen.

Ich löse das z.B. per Perl. Meistens gebe ich jedoch vorher auch die Anzahl aus.

script.pl
#! /usr/bin/perl  
$feld = $ARGV[0];
while (<STDIN>)
{ 
    $ent = $_;
    @werte = split (" ", $ent);
    $eintrag = $werte[$feld];  
    $sum{$eintrag}++;
}
foreach $ent (keys %sum)
{
  $zahl = sprintf "%06d", $sum{$ent} ;
  print $zahl . ";" . $ent . "\n";
}
cat datei.txt | ./script.pl 1 | sort -r

Ausgabe:

000003;host5
000003;host1
000002;localhost
000002;host4
000002;host3
000001;host2

Alternativ kann man natürlich das "sprintf" weglassen und mit "sort -gr" sortieren, erhöht jedoch bei vielen Einträgen nicht gerade die Übersicht.

cryptosteve

(Themenstarter)
Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

Hi, vielen Dank zunächst für Deine Antwort. Es freut mich schonmal, dass es offenbar nicht mal eben so ein trivialer Einzeiler ist, auf den ich bloss nicht gekommen bin. ☺ Dein Skript schaue ich mir gerne mal an, vielleicht kann ich das für meine Zwecke adaptieren. Die Anzahl vorne einstellig und dann mit Doppelpunkt, dann ist's ja schon gut brauchbar.

Vielleicht fällt ja trotzdem noch jemandem eine egrep- oder sonstwie geartete Lösung ein?!

uname

Anmeldungsdatum:
28. März 2007

Beiträge: 6030

Wohnort: 127.0.0.1

Das Problem ist, dass es über mehrere Zeilen geht. Im Prinzip muss man Werte in Variablen schreiben und die Variablen entsprechen irgendwelchen Bezeichnungen, also Hash-Variablen wie $sum{host1}. Mag sein, dass man das mit "awk" irgendwie bauen kann.

Das Semikolon ist im übrigen recht praktisch für CSV-Dateien und die Weiterbearbeitung in OO Calc bzw. MS Excel. Normalerweise ist die Auswertung dann auch mehrdimensional und nicht ganz so trivial. Die Eingabe über Pipes ist im übrigen recht praktisch um mehrere dieser Mini-Perl-Scripte zu kombinieren.

cryptosteve

(Themenstarter)
Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

Jip, ungefähr bei dem Gedanken bin ich dann auch gescheitert. Einzelne Sachen rauszugreppen ist kein Thema, aber das dann auch noch zu zählen (nicht nur für einen Wert, sonder für alle vorkommenden) hat mich dann doch überfordert.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

echo "1208101519 localhost index.html
1208101519 localhost index.html
1208101519 host1 index.php
1208101519 host2 index1.html
1208101519 host1 index2.html
1208101519 host5 index1.html
1208101519 host4 index.php
1208101519 host3 index1.html
1208101519 host3 index1.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html" | sed 's/[^ ]* //' | sort | count.sh | sort -nr | head -n 5 

2:	localhost index.html
2:	host5 index2.html
2:	host3 index1.html
1:	host5 index1.html
1:	host4 index.php

falls Du nach den Top 5 - Kombinationen suchst, und nicht nach den Top 5 jeweils.

count.sh:

wasmacht.sh count.sh 
/home/stefan/bin/count.sh: ASCII text
echo "/**
	count.sh

	get Input like
	aaa
	aab
	aab
	aac
	aac
	bxy

	and output
	aaa 1
	aab 2
	aac 2
	bxy 1

	Assuming (not testing) input is sorted.

	@author Stefan Wagner (c) GPLv3
	@date Do Mar 18 03:01:49 CEST 2010

*/" > /dev/null 

function count ()
{
	count=0

	while read line
	do
		if [[ $line."foo" = $oldline."foo" ]]
		then
			count=$((count+1))
		else
			if [[ oldline."foo" != ."foo" ]] 
			then
				echo -e $count ":\t" $oldline
			fi
			count=1
			oldline=$line
		fi
	done
	echo -e $count ":\t" $oldline
}

function usage ()
{
	echo -e "Usage:\tcat file | sort | count.sh"
	echo -e "\t\tcounts identic lines."
	echo -e "\t\tassumes lines are sorted ascending, like from 'sort file | count.sh'"
}

if (( $# != 0))
then
	usage 
	exit 1
fi

count

uname

Anmeldungsdatum:
28. März 2007

Beiträge: 6030

Wohnort: 127.0.0.1

War doch trivial. Uniq kann auch zählen, war mir entfallen:

cat datei.txt  | cut -d" " -f2  |sort |uniq -c | sort -gr

cryptosteve

(Themenstarter)
Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

user unknown schrieb:

falls Du nach den Top 5 - Kombinationen suchst, und nicht nach den Top 5 jeweils.

Nein, ich suche einzeln. Es wäre aber kein Problem, das Skript einfach zweimal durchlaufen zu lassen, z.B. einmal mit Parameter "2" (für Spalte zwei), einmal mit "3" (für Spalte 3).

Dazu noch 'ne Idee?

uname

Anmeldungsdatum:
28. März 2007

Beiträge: 6030

Wohnort: 127.0.0.1

Hier nun die Top5 beim Feld 2:

cat datei.txt  | cut -d" " -f2  |sort |uniq -c | sort -gr | head -n 5

cryptosteve

(Themenstarter)
Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

Mhhmm ... das ist ja schonmal sehr schick. Klappt hier im Kurztest, morgen teste ich es am tatsächlichen Logfile.

Antiqua Team-Icon

Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

sort +2 datei.txt | uniq -c | sort -gr

sortiert datei.txt nach
+0 = erstes Feld
+1 = zweites Feld
+2 = drittes Feld

cryptosteve

(Themenstarter)
Avatar von cryptosteve

Anmeldungsdatum:
17. April 2007

Beiträge: 815

Wohnort: Nähe Hamburg

OMG ... es ist doch ein simpler Einzeiler ☹

Trotzdem danke ... 👍

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

Ist dieses -c - Flag bei uniq relativ neu, oder habe ich es nur bisher übersehen? Mir kommt es so vor, als habe ich es vor paar Monaten schonmal gesehen, aber wieder verdrängt, weil es mein schönes count-Programm überflüssig macht. ☺

Antiqua Team-Icon

Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

uniq --version
uniq (GNU coreutils) 6.12
Copyright © 2008 Free Software Foundation, Inc.

hats jedenfalls schon...

Antiqua Team-Icon

Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

noch eine Möglichkeit, diesmal mit awk:

textfile:

1208101519 localhost index.html
1208101519 localhost index.html
1208101519 host1 index.php
1208101519 host2 index1.html
1208101519 host1 index2.html
1208101519 host5 index1.html
1208101519 host4 index.php
1208101519 host3 index5.html
1208101519 host3 index5.html
1208101519 host5 index5.html
1208101519 host5 index5.html
1208101519 host4 index5.html
1208101519 host1 index5.html
1208101519 host3 index5.html
1208101519 host5 index5.html
1208101519 host5 index5.html
1208101519 host4 index5.html
1208101519 host1 index5.html
1208101519 host3 index5.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html
1208101519 host3 index1.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html
1208101519 host3 index1.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html
1208101519 host3 index1.html
1208101519 host5 index2.html
1208101519 host5 index2.html
1208101519 host4 index3.html
1208101519 host1 index4.html

nach den hosts sortiert:

ich@slacker:~/ubuntu/sorttest$ awk '{ print $2 }' textfile | sort | uniq -c | sort -gr
     13 host5
      8 host1
      7 host4
      7 host3
      2 localhost
      1 host2
      1

nach den Seiten sortiert:

ich@slacker:~/ubuntu/sorttest$ awk '{ print $3 }' textfile | sort | uniq -c | sort -gr
     12 index5.html
      9 index2.html
      5 index1.html
      4 index4.html
      4 index3.html
      2 index.php
      2 index.html
      1
Antworten |