[gelöst] Wert aus Zeile lesen - ...

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
ivato
Beiträge: 19
Registriert: 28.03.2003 19:25:20

[gelöst] Wert aus Zeile lesen - ...

Beitrag von ivato » 20.04.2006 21:28:20

Hallo Forum,

bräuchte bitte einen geeigneten bash oder awk Befehl mittels dem ich das
Vorhaben beim * bekomme.
Komme damit irgendwie nicht zurecht. Meine, dies mittels awk zu ermitteln. Hab schon viel recherchiert,
bisher nicht herausgefunden wie ich einen Wert mit awk lesen kann, prüfe und ggfs. nur den nächsten Wert lese.

Da dies meine erste "grössere" script Aufgabe ist, sind jegliche Anregungen willkommen.
Auch, was den Ablauf betrifft.

Vielen Dank schon mal.


Pseudo
----------
- finde eine Anzahl Verzeichnisse (können beliebig viele sein)
- schreibe Verzeichnisgröße und Name in eine Datei mit einer bestimmten Reihenfolge. (1. Spalte = Größe, 2. Spalte = Name)
- lese den 1. Wert (1. Zeile, 1. Feld) aus Datei
- Vergleiche diesen Wert mit einer vorgegebenen Größe (maxsize)
- ist Wert < maxsize
ja
- ist Wert(Summe) + Wert aus nächster Zeile < maxsize *
ja (wiederhole und summiere bis nein)
nein
- besteht bereits eine datei.xxx (z.B. datei.001)
nein
- schreibe die Zeile(n), die annähernd die Größe von maxsize haben in eine neue Datei -> datei.001
- lösche die entsprechenden Zeilen aus original Datei
ja
- schreibe neue datei.xxx (xxx inkrementiert)
- lösche wiederum die zeilen
- wiederholen bis original Datei keine Zeilen enthält
Zuletzt geändert von ivato am 21.04.2006 17:56:36, insgesamt 1-mal geändert.

floschi
Beiträge: 791
Registriert: 17.09.2002 14:36:18
Wohnort: München
Kontaktdaten:

Beitrag von floschi » 20.04.2006 21:38:21

warum nicht Perl?

ivato
Beiträge: 19
Registriert: 28.03.2003 19:25:20

Beitrag von ivato » 20.04.2006 21:58:13

da mir die Lernkurve zum "programmieren" über bash scripting, Bordmittel, leichter erscheint.

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 20.04.2006 22:10:46

Wenn das so wäre, wäre perl nicht so erfolgreich ;)
Mit perl dürfte dein Problem wahrscheinlich schneller zu lösen sein.

ivato
Beiträge: 19
Registriert: 28.03.2003 19:25:20

Beitrag von ivato » 20.04.2006 22:37:20

OK.
Danke für den Hinweis. Ziehe es in betracht.

Könnt Ihr mir eine grobe Einschätzung / Gegenüberstellung (Perl <--> Python) geben,
speziell zu meinem Problem?

Fange gerade auch an mich etwas in Python einzuarbeiten, oder würdet Ihr eher Perl empfehlen?

bash habe ich deshlab gewählt, da schon bischen mehr Erfahrung damit besteht.

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 20.04.2006 23:57:45

Schwierig... Insbesondere, da ich Python-Fan bin ;)

Also was kurze Textmanipulationshacks angeht, ist perl nicht zu schlagen, dafür wurde es ja ursprünglich auch geschrieben.

Wenn du allgemein Programmieren lernen willst und/oder planst, größere Tools zu schreiben, würde ich dir zu Python raten.

Wenn du nur eine Sprache lernen willst, und:

1. Ab und an kleine Scripte wie dieses brauchst, und
2. Es dir nichts ausmacht, das du den Code u.U. in ein paar Wochen nicht mehr lesen kannst,

dann nimm Perl, sonst Python.

Wenn du Lust hast, beides zu lernen, würde ich dir empfehlen, dieses Skript in Perl zu schreiben. Ein bisschen Perl zu können ist nämlich nie verkehrt.

(Wenn dir die klare Syntax von Python nicht so sehr gefällt, und du Perls Kürze und "There's more than one way to do it"-Philosophie magst, solltest du dir auch mal Ruby anschauen)

ToPeG
Beiträge: 437
Registriert: 14.04.2004 00:42:06

Beitrag von ToPeG » 21.04.2006 03:24:23

ich habe mal ein bash Script nach deinen Vorgaben geschrieben. Aber besonders effizient oder schnell ist es nicht (zumal ich nicht gerade ein Meister der darin bin. :oops:) Außerdem ist deine gewünschte Herangehensweise auch nicht gerade die beste. Das ständige öffnen und schließen der Dateien kostet eine Menge Zeit.
Das Script ist nicht lang, darum wage ich es, es mal direckt zu posten :-)

Code: Alles auswählen

#!/bin/bash

# Dateiname für ZwischenAusgabe
TEMP_DAT="/TEMP/test_liste.txt"

# Dateinamen für Ausgabe
LISTE_DAT='datei.%03u'

# Liste von Verzeichnissen dirch Leerzeichen getrennt.
VERZEICHNISSE="/usr/bin/ /etc/ /var/log/";

# Gesammtgröße der Liste in Bite
GROESSE=100000


echo -n > $TEMP_DAT
for dir in $VERZEICHNISSE; do
 echo $dir
 liste=`ls -l $dir | awk '{printf "%u,%s\n",$5,$9}'`
 IFS="
"
 for line in $liste; do
  lang=`expr length "$line"`
  pos=`expr index "$line" ','`
  let pos=pos-1
  gross=`expr substr "$line" 1 $pos`
  let pos=pos+2
  name=`expr substr "$line" $pos $lang`
  if [ $name != "" ]; then
   echo "$gross,$dir$name" >>  $TEMP_DAT
  fi
 done
IFS=" "
done

summe=0
cnt=0
IFS="
"
TEMP_DAT_NEU="$TEMP_DAT.neu"
echo $TEMP_DAT_NEU

while [ -s $TEMP_DAT ]; do
 echo "C=$cnt"
 cntb=0
 echo -n > $TEMP_DAT_NEU
 for line in `cat $TEMP_DAT`; do
  if [ $cntb -eq 0 ]; then
   cntb=1
   lang=`expr index "$line" ','`
   let lang=lang-1
   gross=`expr substr "$line" 1 $lang`
   let summe=summe+gross
   if [ $summe -ge $GROESSE ]; then
    summe=0
    let cnt=cnt+1
    name=`printf $LISTE_DAT $cnt`
    echo $line > $name
   else
    name=`printf $LISTE_DAT $cnt`
    echo $line >> $name
   fi
  else
   echo $line >> $TEMP_DAT_NEU
  fi
 done
 rm $TEMP_DAT
 mv $TEMP_DAT_NEU $TEMP_DAT
done
Als Dreingabe habe ich das ganze nochmal in Perl geschrieben. Damit du sehen kannst wo die unterschiede sind. Es ist nur maginal kürzer.

Code: Alles auswählen

#!/usr/bin/perl

use strict;

# Dateiname für ZwischenAusgabe
my $TEMP_DAT='/TEMP/test_liste.txt';

# Dateinamen für Ausgabe
my $LISTE_DAT='datei.%03u';

# Liste von Verzeichnissen dirch Leerzeichen getrennt.
my @VERZEICHNISSE=qw|/usr/bin/ /etc/ /var/log/|;

# Gesammtgröße der Liste in Bite
my $GROESSE=100000;

open(TEMP ,'>',$TEMP_DAT) or die "konnte \"$TEMP_DAT\" nicht öffnen! ($!)\n";
for my $dir (@VERZEICHNISSE)
{
 for my $name (<$dir*>)
 {
  my $gross=-s $name;
  print TEMP "$gross,$name\n";
 }
}
close(TEMP);

my $summe=0;
my $cnt=0;
while(-s $TEMP_DAT)
{
 open(TEMP ,'+<',$TEMP_DAT) or die "konnte \"$TEMP_DAT\" nicht öffnen! ($!)\n";
 my $line=<TEMP>;
 chomp($line);
 my ($gross, $name)=split(',',$line);
 my $rest="";
 while($_=<TEMP>)
 { $rest.=$_; }
 seek(TEMP,0,0);
 truncate(TEMP,0);
 print TEMP $rest;
 close(TEMP);
 $summe+=$gross;
 if($summe > $GROESSE)
 {
  $summe=0;
  $cnt++;
  my $out_name=sprintf($LISTE_DAT,$cnt);
  open(OUT, '>', $out_name) or die "Konnte \"$out_name\" nicht öffen ($!)\n";
  print OUT "$gross,$name\n";
  close(OUT);
 }
 else
 {
  my $out_name=sprintf($LISTE_DAT,$cnt);
  open(OUT, '>>', $out_name) or die "Konnte \"$out_name\" nicht öffen ($!)\n";
  print OUT "$gross,$name\n";
  close(OUT);
 }
}
Und so würde ich es in perl Schreiben (bash wäre äquivalent)

Code: Alles auswählen

#!/usr/bin/perl

use strict;

# Dateinamen für Ausgabe
my $LISTE_DAT='datei.%03u';

# Liste von Verzeichnissen dirch Leerzeichen getrennt.
my @VERZEICHNISSE=qw|/usr/bin/ /etc/ /var/log/|;

# Gesammtgröße der Liste in Bite
my $GROESSE=100000;

my $summe=0;
my $cnt=0;
my $out_name=sprintf($LISTE_DAT,$cnt);
open(OUT, '>', $out_name) or die "Konnte \"$out_name\" nicht öffnen ($!)\n";
for my $dir (@VERZEICHNISSE)
{
 for my $name (<$dir*>)
 {
  my $gross=-s $name;
  $summe+=$gross;
  if($summe > $GROESSE)
  {
   $summe=0;
   $cnt++;
   close(OUT);
   $out_name=sprintf($LISTE_DAT,$cnt);
   open(OUT, '>', $out_name) or die "Konnte \"$out_name\" nicht öffnen ($!)\n";
  }
  print OUT "$gross,$name\n";
 }
}
close(OUT);
@Joghurt
Nunja ich finde Phyton unübersichtlich. Ich habe mich zwar schon mal damit beschäftigt, und mache Ansätze sind wirklich interessant, aber Perl gefällt mir einfach besser. (Und kann meinen Perlcode noch nach Jahren lesen.)

ivato
Beiträge: 19
Registriert: 28.03.2003 19:25:20

Beitrag von ivato » 21.04.2006 17:55:52

@Joghurt
Vielen Dank, Deine Aussage hilft mir ein Bild zu machen fürs weitere Vorgehen.

@ToPeG
Ebenfalls vielen Dank für die Mühe.
Da ich mich nicht festgelegt habe auf eine Spache, werde ich, wie es Joghurt auch empfohlen hat, den versuch mit Perl starten und Dein Code als Vergleich nutzen.

ToPeG
Beiträge: 437
Registriert: 14.04.2004 00:42:06

Beitrag von ToPeG » 21.04.2006 23:11:07

Um das ganze etwas spannender für dich zu machen.
In allen Scripten steckt der selbe Denkfehler. Die Scripte funktionieren nicht 100 prozentig korrekt. Die Fehlerbehebung ist ganz simpel. (Man sollte keine Scripte nach zwei Uhr nachts schreiben.) :-)

Antworten