Zeilenweiser Vergleich und Ergebnis anhängen

J

jodaine

Grünschnabel
Hallo,

ich bin Änfängerin im shellskripten und bräuchte mal eure Hilfe.

Ich habe eine Datei mit Dateieinträgen, die mit ihren md5-Hashwert aufgelistet sind. Leider haben die Einträge nicht immer die gleichen Pfadangaben.

Datei1 (Beispiel):

Code:
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59123.page
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59124.page
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59135.page
6b290e7b48f8a58e188b1a916f8ef56e ./tmp.build/59110.page
6b290e7b48f8a58e188b1a916f8ef56e ./tmp.build/59111.page
6cde362c9262abe3281b5fc7357c7f19 ./tmp.build/82834.page
...

Mit den Befehlen sort und uniq habe ich es schon geschafft alle Einträge zu sortieren und doppelte zu entfernen. :hilfe2:

Aber jetzt benötige ich hinter dem letzten Vorkommen eines md5-Hashwertes die Anzahl der gesamten Vorkommen. :think:

Es soll dann etwa so ausschauen:

Code:
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59123.page
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59124.page
67bfb1f48600c36374a4c73bf62901ac ./tmp.build/59135.page
Anzahl: 3
6b290e7b48f8a58e188b1a916f8ef56e ./tmp.build/59110.page
6b290e7b48f8a58e188b1a916f8ef56e ./tmp.build/59111.page
Anzahl: 2
6cde362c9262abe3281b5fc7357c7f19 ./tmp.build
...

Könntet ihr mir weiterhelfen? Ich benutze die bash-Shell unter Unix.
 
Wenn's denn unbedingt als reines Shell-Skript sein soll ... sowas könnte funktionieren:
Code:
#!/bin/sh

exec 0<Datei1
while read MD5 NAME; do
        [ "$PREV_MD5" = "$MD5" ] && N=`expr ${N:-0} + 1` || { [ ${N:-0} -gt 0 ] && echo "Anzahl: $N"; N=1; }
        echo $MD5 $NAME
        PREV_MD5="$MD5"
done
echo "Anzahl: $N"
... würde selbst aber wahrscheinlich eher zu Perl oder awk tendieren ...

Grüße
 
Super es hat funktioniert :D

Wie würde es dennmit awk funktionieren?
 
Code:
#!/bin/sh

exec 0<Datei1
while read MD5 NAME; do
        [ "$PREV_MD5" = "$MD5" ] && N=`expr ${N:-0} + 1` || { [ ${N:-0} -gt 0 ] && echo "Anzahl: $N"; N=1; }
        echo $MD5 $NAME
        PREV_MD5="$MD5"
done
echo "Anzahl: $N"

Hi floyd62!

Irgendwie sieht dieses Konstrukt ziemlich tricky aus. Kannst du das mal kommentieren, ich würde das gerne verstehen. Wäre sehr nett, Danke!
 
Hi angelsfall,

na, ich versuch's mal: :think:

Ich les' also mit der while-Scheife jeweils zwei Strings in die Variablen MD5 und NAME, und check erst mal ab, ob ich den aktuellen MD5-Hash schon mal gesehen habe:

Code:
while read MD5 NAME; do
        [ "$MD5" = "$PREV_MD5" ]

Ist das der Fall, dann zähl ich N hoch

Code:
        && N=`expr $N + 1`

ansonsten gebe ich aus, wie oft ich den vorherigen Wert gesehen habe, und setze N auf 1 zurück

Code:
       || { echo "Anzahl: $N"; N=1; }

Naja, dann gebe ich die gerade eingelesene Zeile aus, merke mir den aktuellen Wert von MD5 als PREV_MD5, und beende das Ganze ...

Code:
       echo $MD5 $NAME
       PREV_MD5=$MD5
done

Der Rest ist kosmetisches Gehampel: ${N:-0} statt $N stellt sicher, dass mir die Shell nicht um die Ohren fliegt, nur weil N noch nicht gesetzt ist; wenn N = 0 ist, brauch ich die Anzahl nicht ausgeben etc.

Und mit dem
Code:
exec 0<Datei1
ganz oben stell ich sicher, daß die while-Schleife im aktuellen Prozess ausgeführt wird, damit der Wert von N auch nach der Schleife noch steht, und ich auch für den letzten Hash noch die Anzahl angeben kann ...

Alles klar? Na also ... :D
 
Habe mal noch ein paar Versuche mit awk gemacht. Mit dem folgenden Code schaffe ich es die Gesamtanzahl jedes Hashwertes anzuzeigen.

PHP:
cat Datei1| awk '{zaehler[$1]+=1} END {for (F in zaehler) {print F; print "\n Anzahl: " zaehler[F];}}' > Outputfile

Dann sieht die Ausgabe so aus:

PHP:
e22858af473e453082d4710ae64e0fa7 Anzahl: 3
43868ff4ce3f5c5216ecb4168e627a8c  Anzahl: 1
97a53fab452465157d15dbe997b44bb7 Anzahl: 1
b160a3c087e8b841ed7bb4ebe73b71d6 Anzahl: 14

Wie schaffe ich das jetzt evtl. nach der Anzahl zu sortieren? :think:
 
Habe mal noch ein paar Versuche mit awk gemacht. Mit dem folgenden Code schaffe ich es die Gesamtanzahl jedes Hashwertes anzuzeigen.

PHP:
cat Datei1| awk '{zaehler[$1]+=1} END {for (F in zaehler) {print F; print "\n Anzahl: " zaehler[F];}}' > Outputfile

useless use off cat
Dann sieht die Ausgabe so aus:

PHP:
e22858af473e453082d4710ae64e0fa7 Anzahl: 3
43868ff4ce3f5c5216ecb4168e627a8c  Anzahl: 1
97a53fab452465157d15dbe997b44bb7 Anzahl: 1
b160a3c087e8b841ed7bb4ebe73b71d6 Anzahl: 14

Wie schaffe ich das jetzt evtl. nach der Anzahl zu sortieren? :think:

Entweder du nimmst sort, (-n -k3) oder du machst es gleich in perl.
Code:
perl -ane '$h{$F[0]}++; END{printf "%s25\tAnzahl:%3i\n" ,$_,$h{$_} for sort {$h{$a}<=>$h{$b}} keys %h}'  inputfile >outputfile

Gruß Wolfgang
 
Zurück
Oben