PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Aus Dateien was "rausschneiden"



Janine123
28-08-2007, 12:49
Hallo Jungs,

ich hab z.B. eine "configfile"

mit dem Inhalt:

[ü1]
abc=1
bac=2
cba=3
[ü2]
abc=2
bac=1
cba=3
[ü3]
...
...
...

So also dieses File ist in Abschnitte mit Überschriften unterteilt die immer mit "[]"

gekennzeichnet sind und ich möchte jetzt wissen wie ich aus der ganzen Datei

immer nur einen Abschnitt z.B. den Abschnitt "[ü1]" mit allen Werten darunter bis Abschnitt [ü2] rausschneide und in einem anderen File abspeicher kann so das es in dem anderen File nur das gäbe...

[ü1]
abc=1
bac=2
cba=3

Achja und die Überschriften in den [] müssten variablen sein.

jan61
28-08-2007, 16:13
Moin,

Variante 1 mit awk:
jan@jack:~/tmp/fcut> cat get_sect.awk
BEGIN { print_it = 0;
sect = ""; }
$1 ~ /^\[.+\]$/ { sect = substr($1, 2, length($1) - 2);
if (sect == par_sect)
print_it = 1;
else
print_it = 0; }
{ if (print_it == 1) print $0; }
jan@jack:~/tmp/fcut> awk -f get_sect.awk -v par_sect=ü2 config.txt
[ü2]
abc=2
bac=1
cba=3
Variante 2 mit Perl:
jan@jack:~/tmp/fcut> cat get_sect.pl
#! /usr/bin/perl

use strict;
use warnings;

die "usage: get_sect.pl section\n" unless defined $ARGV[0];
my $par_sect = $ARGV[0];

my $print_it = 0;
my $sect = "";
while (<STDIN>) {
if (/^\[.+\]$/) {
($sect) = $_ =~ m/^\[(.+)\]$/;
if ($sect eq $par_sect) {
$print_it = 1;
}
else {
$print_it = 0;
}
}
print $_ if $print_it == 1;
}
exit 0;
jan@jack:~/tmp/fcut> ./get_sect.pl ü2 <config.txt
[ü2]
abc=2
bac=1
cba=3
Jan

reneeb
01-09-2007, 15:04
Dafür kann man auch Config::IniFiles verwenden...

jan61
03-09-2007, 10:12
Dafür kann man auch Config::IniFiles verwenden...

Ja, kann man und ist auch sicher besser, wenn man mit den Einträgen weiterarbeiten will. Für diesen einfachen Fall erspart das nicht viel Arbeit (man muss parsen, suchen und die Ausgabe wieder zusammenbauen):

#! /usr/bin/perl

use strict;
use warnings;
use Config::IniFiles;

die "usage: get_sect.pl file section\n" unless defined $ARGV[0] && defined $ARGV[1];
my $cfg = new Config::IniFiles( -file => $ARGV[0]);
my $par_sect = $ARGV[1];
if (!$cfg->SectionExists($par_sect)) {
die "section $par_sect does not exist in ini file";
}

print "[", $par_sect, "]\n";
my @params = $cfg->Parameters($par_sect);
foreach (@params) {
print $_, "=", $cfg->val($par_sect, $_), "\n";
}
exit 0;
Jan

jan61
04-09-2007, 00:11
Ein anderer Gesichtspunkt, ob und wann man Perl-Module anstatt selbstgeschriebener Routinen verwenden sollte, fiel mir später ein - das Thema hat offensichtlich in meinem Kopf noch rumgespukt :):

Ich habe mir mal eine (zugegebenermaßen übertrieben große) Ini-Datei wie folgt gebastelt:
for i in `seq 1 10000`; do
echo "[sect$i]" >>config.ini
for k in `seq 1 10`; do
echo "par$k=$i$k" >>config.ini
done
done (daraus wurden ca. 1,2 MB) und dann beide Varianten mal laufen lassen (get_sect.pl ist die handgestrickte Variante, get_sect2.pl diejenige, die Config::IniFiles benutzt):
jan@jack:~/tmp/fcut> time ./get_sect.pl sect5000 <config.ini >config_teil.ini

real 0m0.116s
user 0m0.094s
sys 0m0.003s
jan@jack:~/tmp/fcut> time ./get_sect2.pl config.ini sect5000 >config_teil2.ini

real 1m16.293s
user 1m16.145s
sys 0m0.079s
Bei einer config.ini mit 1.000 statt 10.000 Sektionen (110 KB) sah es immer noch so aus:
jan@jack:~/tmp/fcut> time ./get_sect.pl sect500 <config.ini >config_teil.ini

real 0m0.021s
user 0m0.018s
sys 0m0.004s
jan@jack:~/tmp/fcut> time ./get_sect2.pl config.ini sect500 >config_teil2.ini

real 0m1.094s
user 0m1.083s
sys 0m0.010s
Der Ini-Parser liest offensichtlich erst die gesamte Datei ein, parst sie und stellt erst dann die Ergebnisse bereit. Einer der Prozessoren war in dieser Zeit mit 100% ausgelastet. Man sollte also meiner Meinung nach - wenn keine Notwendigkeit besteht, die Datei zu validieren oder die Ergebnisse weiterzuverwenden - lieber mal die Arme-Leute-Version (selbstgebastelt) nehmen - das spart unter Umständen viel Zeit, auch bei kleineren Ini-Files, wenn man oft drübergehen muss.

Jan

P.S.: awk ist noch nen Tick schneller:
jan@jack:~/tmp/fcut> time awk -f get_sect.awk -v par_sect=sect500 config.ini >config_teil3.ini

real 0m0.016s
user 0m0.014s
sys 0m0.001s