PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : anfänger frage script soll zählen



Mehlwurm
05-06-2012, 08:43
hallo,

ich habe ein text datei, in der ein muster immerwieder vorkommt, zwei zeilen nach dem muster brauch ich die anzahl der elemente (worte in der reihe) ...

und hab gerade garkeinen plan, wie ich das anstellen soll ???

> grep "MUSTER" file_name | wc -l
sagt mir, dass es 9164 mal vorkommt, also bitte lasst mich das nicht händisch raussuchen ;-)

danke für eure hilfe

jeebee
05-06-2012, 19:16
Test-Input:
MUSTER
a
a b c
MUSTER
aaa a
dddd dd b bsildhf
lsdkjf
slkdfj
MUSTER
a
128
MUSTER
a
128 2

In Bash:
> grep -n "MUSTER" file_name | cut -d':' -f1
gibt alle Zeilennummern in denen "MUSTER" vorkommt zurück
> head -n x file_name | tail -n 1 | wc -w
gibt die Anzahl Elemente (mit Whitespace als Trennzeichen) auf Linie x zurück.

edit:
Perl: "$x = split /\s+/, $line" entspricht "echo $line | wc -w"
Python: "len(line.split())" entspricht "echo $line | wc -w"

Den Loop um diese Bausteine lass ich dem geneigten Leser als Übung ;)

edit2: Bonuspunkte für Bash-Lösung die das File nicht pro gefundene Zeile einmal einliest

Mehlwurm
08-06-2012, 15:05
#!/bin/sh

datei=hunderzeilen.txt

funkt()
{
head -n $1 $datei | tail -n 1 | wc -w
}

abfrage ()
{
head -n $1 $datei | tail -n 1
}

for i in `grep -n "(FPL" $datei | cut -d':' -f1`
do
j=`expr $i + 3`
k=`expr $j + 1`
echo `abfrage $k` #Routenpunktzeile +1 Ausgabe
erstes_zeichen=`echo \`abfrage $k\` | cut -c 1`
if [ $erstes_zeichen != "-" ]
then
zweite_zahl=`funkt $k`

else
echo "minus"

fi
done


<<<< Die Bonuspunkte hole ich mir so sicher nicht ;-)

Mehlwurm
08-06-2012, 15:11
ahso .. das if ist nötig, da in der folgezeile auch noch zu zählende elemente sein können, wenn die zeile nicht mit einem minus beginnt ;-)

Mehlwurm
15-06-2012, 15:00
#!/bin/sh

datei=fpls.txt

funkt()
{
head -n $1 $datei | tail -n 1 | wc -w
}

abfrage ()
{
head -n $1 $datei | tail -n 1
}


for i in `grep -n "(FPL" $datei |cut -d':' -f1`
do
# echo $i #Zeile mit Muster
j=`expr $i + 3`
# echo $j #Zeile mit Routenpunkte
erste_zahl=`funkt $j`
# echo $erste_zahl #Anzahl der Routenpunkte in Zeile 1
k=`expr $j + 1`
# echo $k #Routenpunktzeilennummer +1
# echo `abfrage $k` #Routenpunktzeile +1 Ausgabe
erstes_minus=`abfrage $k | cut -c 1`
if [ "$erstes_minus" != "-" ]
then
# echo "kein minus"
zweite_zahl=`funkt $k`
summe_eins=`expr $zweite_zahl + $erste_zahl`
# echo $summe
m=`expr $k + 1` #dritte mögliche zeile
zweites_minus=`abfrage $m | cut -c 1`
if [ "$zweites_minus" != "-" ]
then
dritte_zahl=`funkt $m`
summe_zwei=`expr $summe_eins + $dritte_zahl`
n=`expr $m + 1`
drittes_minus=`abfrage $n | cut -c 1`
if [ "$drittes_minus" != "-" ]
then
vierte_zahl=`funkt $n`
summe_drei=`expr $summe_zwei + $vierte_zahl`
p=`expr $n + 1`
viertes_minus=`abfrage $p | cut -c 1`
if [ "$viertes_minus" != "-" ]
then
fin_zahl=`funkt $p`
summe_vier=`expr $summe_drei + $fin_zahl`
q=`expr $p + 1`
fin_minus=`abfrage $q | cut -c 1`
if [ "$fin_minus" != "-" ]
then
xxx_zahl=`funkt $q`
echo `expr $summe_vier + $xxx_zahl`
else
echo $summe_vier
fi
else
echo $summe_drei
fi
else
echo $summe_zwei
fi
else
echo $summe_eins
fi
else
# echo "minus"
echo $erste_zahl #Anzahl der Routenpunkte in Zeile 1
fi
done
exit 0


laufzeit ist eine katastrophe und diese if-verschachtelung hätte man sicher auch schick mit einer for schleife lösen können, aber ich brauchte nur einmal das ergebnis, also werd ich es wahrscheinlich nicht optimieren ..
danke für die konstruktiven anregungen

sorry, dass die einrückungen verloren gegangen sind

sportliche grüsse

Markus

undefined
16-06-2012, 11:03
Die Laufzeit ist deshalb so schlecht weil du immer wieder in den Funktionen einen Datei-Descriptor öffnest.

Beim Arbeiten mit größeren Dateien ist es Sinnvoller mit Temporären Inhalten zu Arbeiten b.z.w. diese in eine Temp Datei aus zu lagern.

Zeige mal einen Beispiel Inhalt der Datei und Beschreibe was du machen möchtest.

jeebee
16-06-2012, 11:14
Ich werfe mal noch
line=1
target_line=0
while read line_contents; do
if [ $line -eq $target_line ]; then
echo $line_contents | wc -w
fi
echo $line_contents | grep "(FPL" > /dev/null
if [ $? -eq 0 ]; then
# linie mit "(FPL" gefunden
target_line=$(( $line + 3 ))
fi
line=$(( $line+1 ))
done < input in den Raum.

In dieser Lösung wird die Datei nur einmal eingelesen; allerdings fehlt das Erkennen, ob die folgende Zeile auch noch zum Resultat gehört, dies sollte aber relatv einfach möglich sein.

PS: $(( $line+1 )) ist bash Funktionalität für einfache Rechenoperationen.