Schrift
[thread]6674[/thread]

von shell-script nach perl



<< |< 1 2 >| >> 14 Einträge, 2 Seiten
Gast Gast
 2005-01-29 02:00
#51416 #51416
hallo,

ich gebe offen zu, ich habe von perl wenig ahnung.
momentan benutze ich ein shell-script dazu aus zwei text-files eine html zu machen. das dauert leider sehr lange. das source file ist zumindest über 6000 zeilen lang. ich vermute das liegt daran, daß die verwendeten utils einfach nicht für so einen zweck gemacht wurden...
und ich habe halt die hoffnung, dass das mit perl besser funktionieren würde

vielleicht ist ja hier jemand so nett und übersetzt mir die paar zeilen kurz, damit ich das ausprobieren kann.
das wäre sehr lieb
vielen dank im vorraus dafür
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#! /bin/bash

main() {
 htmlhead "IP Tabelle"
 tablehead
 file2table ip xxx
 tablefoot
 htmlfoot
}

htmlhead() {
       echo "<html><title>$1</title><body>"
}

htmlfoot() {
       echo "</body></html>"
}


file2table() {
       FILE=$1
       HIGHLITE=$2

       for LINE in $(cat $FILE.raw|tr " " "|"); do
               HOST=`echo $LINE|cut -d "|" -f 2`
               IP=`echo $LINE|cut -d "|" -f 3`

               echo -n "<tr>"
               if [ `echo $HOST|grep $HIGHLITE` ]; then
                       BA="<b>"; BE="</b>"
               else
                       BA=""; BE=""
               fi

               echo -n "<td>$BA$HOST$BE</td><td>$BA$IP$BE</td>"

               DESC=`cat $FILE.desc|grep $HOST|cut -f 2-`
               if [ "$DESC" ]; then echo -n "<td>$BA$DESC$BE</td>"; fi

               echo "</tr>"
       done
}

tablehead() {
       echo "<table>"
}

tablefoot() {
       echo "</table>"
}

main
\n\n

<!--EDIT|renee|1106993737-->
lichtkind
 2005-01-29 12:23
#51417 #51417
User since
2004-03-22
5680 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
im groben geht das genauso in perl nur:

1. es heisst print nicht echo
2. eine sub fängt mit sub an also sub htmlfoot{} auch ohne runde klammern
3. nach jedem befehl ein ";"
4. es geht auhc ohne main
5. shebang ruft perl
6. if (bedingung == wahr) {tue was} else {was anderes}
7. $variablen fangen immer mit $ an den geld ist schön
8.\n\n

<!--EDIT|lichtkind|1106994461-->
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
lichtkind
 2005-01-29 13:11
#51418 #51418
User since
2004-03-22
5680 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
7.2 also $FILE=$ARGV[0];
$HIGHLITE=$ARGV[1];
denn die parameter sind in @ARGV drin besser aber ist nocht:
$FILE = shift;
$HIGHLITE = shift;
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
Dubu
 2005-01-29 14:49
#51419 #51419
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Ich glaube gerne, dass das lange dauert. Das liegt IMHO aber weniger an den "verwendeten utils" selber, sondern mehr daran, dass in jedem Schleifendurchlauf neun(!) Subprozesse erzeugt werden; das macht bei 6000 Zeilen immerhin 54000 neue Prozesse.

Um das effizient in Perl umzuschreiben, waere es aber gut, wenn du uns noch etwas ueber die Eingabedaten verraetst. Zum Beispiel kann ich so nicht sehen, warum du in jeder Zeile Leerzeichen durch Pipezeichen ersetzt, dann aber nur einzelne Eintraege herauspickst. Oder was in $FILE.desc steht und ob es sich nicht lohnt, das im Speicher zu halten, statt es fuer jede Eingabezeile neu zu durchsuchen.
blackbit
 2005-01-29 17:19
#51420 #51420
User since
2005-01-29
7 Artikel
BenutzerIn
[Homepage] [default_avatar]
hallo,

als erst einmal vielen dank für die antworten, das ist sehr freundlich.
es mag sein, dass sich die aufgabe eleganter lösen lässt, ich bin für alle vorschläge offen.

also zu den daten, die schauen im allgemeinen so aus:

in dem raw file stehen hostnamen mit dazugehörigen ip-adressen.
host1.subdomain.domain.xx 10.10.10.1
host2.subdomain.domain.xx 10.10.10.2

in dem desc file stehen anmerkungen, wie z.b.
host1.subdomain.domain.xx workstation josef huber
host2.subdomain.domain.xx mail exchanger prority 20

dabei ist die beschreibung selber durch einen tab vom hostnamen getrennt.

hat jemand eine idee wie sich das (gerne auch effizienter) unter perl abbilden lässt?

danke
blackbit
 2005-01-29 21:33
#51421 #51421
User since
2005-01-29
7 Artikel
BenutzerIn
[Homepage] [default_avatar]
ich hab mich jetzt einmal dazu entschlossen mein shell-script 1:1 in perl zu übersetzen und dann später u.u. verbesserungen vorzunehmen. ich hab schon damit angefangen, wobei angehäntes ergebnis raus gekommen ist. das script ist so lauffähig, allerdings hätte ich mir als ausgabe erwartet:
[html]
<html><title>IP Tabelle</title><body>
<table>
</table>
</body></html>[/html]

statt dessen ist aber nur das gekommen:
[html]<html><title></title><body>[/html]

offensitchlich habe ich einen fehler gemacht in der übergabe der variable "IP Tabelle" an die subroutine htmlhead, das ist mir schon klar.
was ich nicht verstehe ist, daß offenbar nur die sub htmlhead ausgeführt wird, sonst nix, und dass ich dazu keine fehlermeldung bekomme.
ich bitte um aufklärung eines blutiges perl-neulings
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
sub main
{
        htmlhead ("IP Tabelle");
        tablehead;
        file2table ("ip xxx");
        tablefoot;
        htmlfoot;
}

sub htmlhead
{
        print "<html><title>$1</title><body>\n";
}

sub htmlfoot
{
        print "</body></html>";
}

sub file2table
{
}

sub tablehead
{
        print "<table>";
}

sub tablefoot
{
        print "</table>";
}

main;


edit renee: [html]- und [perl]-Tags spendiert...\n\n

<!--EDIT|renee|1107087460-->
blackbit
 2005-01-29 22:03
#51422 #51422
User since
2005-01-29
7 Artikel
BenutzerIn
[Homepage] [default_avatar]
ok, das mit der variable hab ich schon geschafft, die sub schaut jetzt so aus:
Code (perl): (dl )
1
2
3
4
5
sub htmlhead
{
        my $var = shift;
        print "<html><title>$var</title><body>\n";
}


bleibt immer noch die frage:
warum wird nur htmlhead ausgeführt?\n\n

<!--EDIT|renee|1107087507-->
blackbit
 2005-01-29 22:08
#51423 #51423
User since
2005-01-29
7 Artikel
BenutzerIn
[Homepage] [default_avatar]
so, das problemchen hab ich jetzt auch in den griff bekommen.
momentaner code schaut so aus:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
sub main
{
htmlhead("IP Tabelle");
tablehead();
file2table("ip xxx");
tablefoot();
htmlfoot();
}

sub htmlhead
{
my $var = shift;
print "<html><title>$var</title><body>\n";
}

sub htmlfoot
{
print "</body></html>\n";
}

sub file2table
{
}

sub tablehead
{
print "<table>\n";
}

sub tablefoot
{
print "</table>\n";
}

main;


jetzt gehts an die for schleife...
dazu brauch ich als allererstes die anzahl der zeilen vom .raw file.
hier stosse ich sehr deutlich an meine grenzen, nachdem ich gar keine vorkenntnisse hab...
aber ich ja schon froh, dass ich überhaupt so weit gekommen bin.
ist jemand so lieb und hilft mir?\n\n

<!--EDIT|blackbit|1107029757-->
Ronnie
 2005-01-29 23:29
#51424 #51424
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
So, erstmal ein wenig perl:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/perl

use strict;
use warnings;

use CGI;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use HTML::Template;
use Tie::File;
#use Data::Dumper qw(Dumper);

my $q = new CGI;
my $file = shift @ARGV;
my $mark = shift @ARGV;

my $file_raw  = $file.".raw";
my $file_desc = $file.".desc";

#print $q->header(), Dumper(&process_files());
print $q->header(), &fill_template(&process_files());
exit;

sub process_files {
  my @file_raw;
  my @result_set;
  tie @file_raw, 'Tie::File', $file_raw or die "Can't tie to file $file_raw: $!\n";
  @result_set = map { 
    my (undef, $host, $ip ) = split(" ", $_);
    my $highlight = ($host =~ /$mark/g) ? 'mark' : undef;
    { host => $host, ip => $ip, highlight => $highlight, };
  } 
  @file_raw;
  return \@result_set;
}

sub fill_template {
  my $recordset = shift;
  my $template = HTML::Template->new(
    filename => "report.tmpl",
    die_on_bad_params => 0,
  );
  $template->param( title => 'Entwurf V2.0', recordset => $recordset, );
  return $template->output;
}

dann das Template:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
<title><TMPL_VAR name="title"></title>
<style>
<!--
.mark { color: #f00; }
-->
</style>
</head>
<body>
<table>
<TMPL_LOOP name="recordset">
<tr class='<TMPL_VAR name="highlight">'>
<td><TMPL_VAR name="ip"></td>
<td><TMPL_VAR name="host"></td>
</tr>
</TMPL_LOOP>
</table>
</body>
</html>

dann meine test.raw:
Code: (dl )
1
2
x host1.subdomain.domain.xx 10.10.10.1
x host2.subdomain.domain.xx 10.10.10.2

Es erfüllt noch nicht komplett deine Anforderung, aber es zeigt wie es sauber in Perl gelöst werden kann. Wenn ich es noch etwas ausbauen soll sage mir Bescheid.
Dubu
 2005-01-30 13:25
#51425 #51425
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Ronnies Vorschlag finde ich klasse. Vor allem ist es nett, die Markierung mit CSS vorzunehmen. Leider braucht man noch HTML::Template, was nicht zur Standardausruestung gehoert. Und ein Anfaenger wird sicherlich etwas laenger dafuer brauchen, die map()-Konstruktion zu verstehen. ;)

Ich habe hier mal versucht, das Originalskript von blackbit nachzuprogrammieren, mit nur wenigen prinzipiellen Aenderungen. Anders geloest ist eigentlich nur das Nachschlagen der Beschreibungen, die hier einmalig in einen Hash geladen werden. Leider hat blackbit nicht gesagt, wie gross die ip.desc ist, denn wenn diese zu gross ist, verbraucht diese Loesung zu viel Speicherplatz.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/perl

# Die folgenden beiden Zeilen sollten *immer* in einem Perl-Programm
# stehen, zumindest waehrend Entwicklung und Test. Damit wird man daran
# gehindert, unsichere Konstruktionen zu benutzen ('strict') und vor
# einigen moeglichen Fehlerquellen gewarnt ('warnings').
use strict;
use warnings;

htmlhead('IP Tabelle');
tablehead();
file2table('ip', '1');
tablefoot();
htmlfoot();

exit 0; # Programmende

########################################
# Hier kommen die Unterroutinen
########################################

sub htmlhead {
   # Die Uebergabeparameter befinden sich im Array @_,
   # das erste Element ist also $_[0]
   print "<html>\n<title>$_[0]</title>\n<body>\n";
}

sub htmlfoot {
   print "</body></html>\n";
}

sub file2table {
   my ($file, $highlight) = @_;

   # Alle Beschreibungen in den Hash %desc einlesen
   my %desc;
   open (DESC, '<', "$file.desc") or die "kann $file.desc nicht oeffnen: $!";
   while (<DESC>) {            # jede Zeile landet im Default-Parameter $_
       chomp();                # Zeilenumbruch am Zeilenende entfernen
       # teile am ersten Whitespace in 2 Teile
       my ($h, $d) = split ' ', $_, 2;
       # Schluessel ist der Host, Wert die Beschreibung
       $desc{$h} = $d;
   }
   close DESC;

   # IPs einlesen
   open (RAW, '<', "$file.raw") or die "kann $file.raw nicht oeffnen: $!";
   while (<RAW>) {             # auch hier jede Zeile einzeln in $_
       # automatisch an Whitespace teilen (alles hinter
       # dem zweiten Whitespace wird ignoriert!)
       my ($host, $ip) = split;

       print '<tr>';
       my ($ba, $be) = ('', '');

       # wenn $highlight irgendwo in $host auftaucht, $ba und $be setzen.
       # $highlight zaehlt dabei - wie bei grep - als Regex-Muster!
       if ($host =~ /$highlight/) {
           $ba = '<b>'; $be = '</b>';
       }

       # Zeile fuer Host ausgeben, evtl mit Beschreibung,
       # wenn sie im Hash existiert, ansonsten mit festem Leerzeichen
       print "<td>$ba$host$be</td><td>$ba$ip$be</td><td>$ba",
           (exists $desc{$host} ? $desc{$host} : '&nbsp;'),
           "$be</td>";

       print "</tr>\n";
   }
   close RAW;
}

sub tablehead {
   print "<table>\n";
}

sub tablefoot {
   print "</table>\n";
}


Edit: Fehlendes <td> ergaenzt, chomp() eingebaut, kaputtes perl-Tag durch code-Tag ersetzt, damit "\n" und "&nbsp;" wieder richtig zu sehen sind. *grmpf*\n\n

<!--EDIT|Dubu|1107094097-->
<< |< 1 2 >| >> 14 Einträge, 2 Seiten



View all threads created 2005-01-29 02:00.