Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rekenbewerking op text file

83 views
Skip to first unread message

Kees de Koster

unread,
Feb 22, 2005, 2:47:36 AM2/22/05
to
Hallo,

Ik heb een text file met verschillende records, ik wil op deze een
rekenbewerking loslaten.

De vier getalen na het "=" teken wil ik vermenigvuldigen met vier, het
laatste getal niet.

19970522000000=1.68,1.68,1.63,1.66,50384
19970523000000=1.66,1.68,1.63,1.68,51213
19970526000000=1.68,1.68,1.61,1.68,28505
19970527000000=1.68,1.68,1.63,1.68,52228
19970528000000=1.66,1.68,1.63,1.68,118430
19970529000000=1.66,1.68,1.61,1.68,260400
19970530000000=1.66,1.66,1.59,1.63,151400
19970602000000=1.63,1.68,1.59,1.68,408740

Iemand een idee hoe ik dat voorelkaar kan krijgen?

GG
Kees
--
Q: Why did Captain Kirk piss on the bridge?
A: He wanted to boldly go where no man had gone before!
Visit me @ http://www.xs4all.nl/~kostercd/ | ICQ #179658498 -- # EOE

Eric Moors

unread,
Feb 22, 2005, 3:17:57 AM2/22/05
to
Kees de Koster wrote:

> Hallo,
>
> Ik heb een text file met verschillende records, ik wil op deze een
> rekenbewerking loslaten.
>
> De vier getalen na het "=" teken wil ik vermenigvuldigen met vier, het
> laatste getal niet.
>
> 19970522000000=1.68,1.68,1.63,1.66,50384
> 19970523000000=1.66,1.68,1.63,1.68,51213
> 19970526000000=1.68,1.68,1.61,1.68,28505
> 19970527000000=1.68,1.68,1.63,1.68,52228
> 19970528000000=1.66,1.68,1.63,1.68,118430
> 19970529000000=1.66,1.68,1.61,1.68,260400
> 19970530000000=1.66,1.66,1.59,1.63,151400
> 19970602000000=1.63,1.68,1.59,1.68,408740
>
> Iemand een idee hoe ik dat voorelkaar kan krijgen?

gawk 'BEGIN {FS=",|=";} { printf "%14d=%0.02f,%0.02f,%0.02f,%0.02f,%d\n",$1
$2*4, $3*4, $4*4, $5*4,$6}' input > output

Eric

Kees de Koster

unread,
Feb 22, 2005, 4:25:26 AM2/22/05
to

Hartelijk dank Eric,

Hij werkt nog niet geheel zoals het moet maar hiermee kom ik er wel.

GG
Kees
--
I am myself plus my circumstance, and if I do not save it, I cannot
save myself.
-- Jos' e Ortega Y Gasset

Koos Pol

unread,
Feb 22, 2005, 7:22:29 AM2/22/05
to
Kees de Koster wrote (Tuesday 22 February 2005 08:47):

> Hallo,
>
> Ik heb een text file met verschillende records, ik wil op deze
> een rekenbewerking loslaten.
>
> De vier getalen na het "=" teken wil ik vermenigvuldigen met
> vier, het laatste getal niet.
>
> 19970522000000=1.68,1.68,1.63,1.66,50384
> 19970523000000=1.66,1.68,1.63,1.68,51213
> 19970526000000=1.68,1.68,1.61,1.68,28505
> 19970527000000=1.68,1.68,1.63,1.68,52228
> 19970528000000=1.66,1.68,1.63,1.68,118430
> 19970529000000=1.66,1.68,1.61,1.68,260400
> 19970530000000=1.66,1.66,1.59,1.63,151400
> 19970602000000=1.63,1.68,1.59,1.68,408740
>
> Iemand een idee hoe ik dat voorelkaar kan krijgen?
>
> GG
> Kees

Met een Perl scriptje bijv.:

use strict;
use warnings;

my $line;
my ($be, $ae); # before equal sign, after equal sign
my @numbers;
while ($line = <DATA>) {
($be, $ae) = split /=/, $line;
@numbers = split /,/, $ae;
pop @numbers;
@numbers = map {$_ * 4} @numbers;
print join " ", map {"[$_]"} @numbers;
print "\n";
}

__DATA__


19970522000000=1.68,1.68,1.63,1.66,50384
19970523000000=1.66,1.68,1.63,1.68,51213
19970526000000=1.68,1.68,1.61,1.68,28505
19970527000000=1.68,1.68,1.63,1.68,52228
19970528000000=1.66,1.68,1.63,1.68,118430
19970529000000=1.66,1.68,1.61,1.68,260400
19970530000000=1.66,1.66,1.59,1.63,151400
19970602000000=1.63,1.68,1.59,1.68,408740

[6.72] [6.72] [6.52] [6.64]
[6.64] [6.72] [6.52] [6.72]
[6.72] [6.72] [6.44] [6.72]
[6.72] [6.72] [6.52] [6.72]
[6.64] [6.72] [6.52] [6.72]
[6.64] [6.72] [6.44] [6.72]
[6.64] [6.64] [6.36] [6.52]
[6.52] [6.72] [6.36] [6.72]

--
KP
Ik krijg overigens uitsluitend virussen van mensen met een
virusscanner. Mensen zonder virusscanner sturen mij nooit
virussen. Gek he? --- V. Sessink in nl.comp.os.linux.overig

John Bokma

unread,
Feb 22, 2005, 12:58:52 PM2/22/05
to
Koos Pol wrote:

> my $line;
> my ($be, $ae); # before equal sign, after equal sign

declareer vars waar je ze gebruikt. Daarnaast, $before_equal,
$after_equal had je dat commentaar kunnen besparen :-D.

> my @numbers;
> while ($line = <DATA>) {

while ( my $line = <DATA> )

> ($be, $ae) = split /=/, $line;

dus hier: my ( $be, $ae )

Andere oplossing:

my ( @numbers ) = $line =~ /(\d+\.\d+)/g;

> @numbers = map {$_ * 4} @numbers;
> print join " ", map {"[$_]"} @numbers;
> print "\n";

print "[",

join ( "] [", map { $_ * 4 } @numbers ),

"]\n";

Als de getallen in een bestand staan, kan:

#!perl -n

use strict;
use warnings;

my ( @numbers ) = $_ =~ /(\d+\.\d+)/g;

print "[",

join ( "] [", map { $_ * 4 } @numbers ),

"]\n";


handig zijn (zie perl -h voor de -n optie)

Of wellicht:

#!perl -n

use strict;
use warnings;

my ( $stamp, @numbers ) = split /[=,]/;
my $count = pop @numbers;

print "$stamp=",

join ( ",", map { $_ * 4 } @numbers ),

",$count";

( merk op dat $count de \n nog bevat )

En een meer awky oplossing:

#!perl -naF[=,]
printf "%14s=%0.02f,%0.02f,%0.02f,%0.02f,%d\n",
$F[ 0 ], ( map { $_ * 4 } @F[ 1..4 ] ), $F[ 5 ];

De "one liner" is left as an excercise ;-)


( merk op: %14s ipv %14d, getal was hier te groot (WinXP) )

--
John Bokma
Voorbeeldscripts in Perl: http://johnbokma.com/perl/
Ervaren Perl / Java programmeur beschikbaar: http://castleamber.com/
Tevreden opdrachtgevers: http://castleamber.com/testimonials.html

Koos Pol

unread,
Feb 23, 2005, 1:33:39 AM2/23/05
to
John Bokma wrote (Tuesday 22 February 2005 18:58):

>> ($be, $ae) = split /=/, $line;
>
> dus hier: my ( $be, $ae )

Nee, want dan haal je de my binnen de loop. En bij een loop van
een miljoen, wil je die er echt buiten hebben :-p


> print "[",
>
> join ( "] [", map { $_ * 4 } @numbers ),
>
> "]\n";

Die gebruikte ik vroeger ook altijd. Ben deze

>> print join " ", map {"[$_]"} @numbers;

een keer in clpm tegen gekomen en vindtum wel zo fraai.

> #!perl -naF[=,]
> printf "%14s=%0.02f,%0.02f,%0.02f,%0.02f,%d\n",
> $F[ 0 ], ( map { $_ * 4 } @F[ 1..4 ] ), $F[ 5 ];

AAAAARRRRGHHHH!!!!
'dorie John, hou daar nu eens me op!

Dr.Ruud

unread,
Feb 23, 2005, 7:55:18 AM2/23/05
to
Toen ik Koos Pol kietelde, kwam er dit uit:
> John Bokma:

>>> ($be, $ae) = split /=/, $line;

>> dus hier: my ( $be, $ae )

> Nee, want dan haal je de my binnen de loop. En bij een loop van
> een miljoen, wil je die er echt buiten hebben :-p

Zou je denken? In sommige talen klopt je denkrichting wel,
maar in andere (gecompileerde) talen wordt op die manier
de variabele nog steeds maar eenmalig opgezet, en daarmee
beperk je zo mooi de scope van die variabele, want hij is
echt 'weg' (onbereikbaar) na de loop.

De vraag is dus: hoe doet perl het.
En perl doet het precies zoals John impliceerde:

A declaration can be put anywhere a statement can, but has no effect
on the execution of the primary sequence of statements -- declarations
all take effect at compile time.
Typically all the declarations are put at the beginning or the end of
the script. However, if you're using lexically-scoped private variables
created with my(), you'll have to make sure your format or subroutine
definition is within the same block scope as the my if you expect to
be able to access those private variables.

Ofwel: alle declaraties worden door de compiler gedaan alsof ze
voorin staan. De scope van de door 'my()' gemaakte variabelen
is beperkt tot de block-scope van het block waarin ze staan.

--
Affijn, Ruud ` - ´
+ ` ´ *
´ ` Jvr qvg yrrfg,
´ = ` fgresg wbatre.


robert

unread,
Feb 23, 2005, 8:15:08 AM2/23/05
to
Dr.Ruud <rvtol...@isolution.nl>:

> A declaration can be put anywhere a statement can, but has no effect
> on the execution of the primary sequence of statements -- declarations
> all take effect at compile time.

$ perl bench 100
Benchmark: timing 100 iterations of in loop, out loop...
in loop: 11 wallclock secs (10.03 usr + 0.00 sys = 10.03 CPU) @ 9.97/s (n=100)
out loop: 6 wallclock secs ( 5.54 usr + 0.00 sys = 5.54 CPU) @ 18.05/s (n=100)

De code:
'in loop' => sub { for (my $i = 0; $i < $num; $i++) { my ($a, $b); } }
'out loop' => sub { my ($a, $b); for (my $i = 0; $i < $num; $i++) { } }
($num = 100000, v5.8.1-RC3)

> Ofwel: alle declaraties worden door de compiler gedaan alsof ze voorin
> staan. De scope van de door 'my()' gemaakte variabelen is beperkt tot de
> block-scope van het block waarin ze staan.

En kennelijk kost de check of een variabele in scope is of niet toch wel
enige rekenkracht.

--
robert

Koos Pol

unread,
Feb 23, 2005, 10:34:09 AM2/23/05
to
On woensdag 23 februari 2005 13:55 Dr.Ruud wrote:

> Ofwel: alle declaraties worden door de compiler gedaan alsof ze
> voorin staan. De scope van de door 'my()' gemaakte variabelen
> is beperkt tot de block-scope van het block waarin ze staan.

Klopt. Maar zoals robert terecht al liet ziet, het punt is niet de
feitelijke declaratie, maar het bepalen van de scope.

Koos
--
43rd Law of Computing: Anything that can go wr
fortune: Segmentation violation -- Core dumped

John Bokma

unread,
Feb 23, 2005, 12:04:22 PM2/23/05
to
Koos Pol wrote:

> John Bokma wrote (Tuesday 22 February 2005 18:58):
>
>>> ($be, $ae) = split /=/, $line;
>>
>> dus hier: my ( $be, $ae )
>
> Nee, want dan haal je de my binnen de loop. En bij een loop van
> een miljoen, wil je die er echt buiten hebben :-p

Omdat?

>> print "[",
>>
>> join ( "] [", map { $_ * 4 } @numbers ),
>>
>> "]\n";
>
> Die gebruikte ik vroeger ook altijd. Ben deze
>
>>> print join " ", map {"[$_]"} @numbers;
>
> een keer in clpm tegen gekomen en vindtum wel zo fraai.


Oh, maar er zit weinig verschil in, alleen doe ik stiekem die maal 4 ook
in die map.

>> #!perl -naF[=,]
>> printf "%14s=%0.02f,%0.02f,%0.02f,%0.02f,%d\n",
>> $F[ 0 ], ( map { $_ * 4 } @F[ 1..4 ] ), $F[ 5 ];
>
> AAAAARRRRGHHHH!!!!
> 'dorie John, hou daar nu eens me op!

Die 14 kan vast weg voor die %, maakt het weer leesbaarder, toch?

John Bokma

unread,
Feb 23, 2005, 12:29:15 PM2/23/05
to
robert wrote:

Benchmark: timing 100 iterations of in, out...
in: 104 wallclock secs (86.56 usr + 0.02 sys = 86.58 CPU) @
1.16/s (n=100)
out: 85 wallclock secs (76.64 usr + 0.01 sys = 76.66 CPU) @
1.30/s (n=100)


use strict;
use warnings;

use Benchmark qw(:all) ;

timethese( 100, {

'in' => sub {

my ( $a, $b );

for ( my $i = 0; $i < 1000000; $i++ ) {

$a = undef;
$b = undef;
$a += $i;
$b += $i;
}
} ,

'out' => sub {

for ( my $i = 0; $i < 1000000; $i++ ) {

my ( $a, $b );

$a += $i;
$b += $i;
}
} ,
});

This is perl, v5.8.3 built for MSWin32-x86-multi-thread
(with 8 registered patches, see perl -V for more detail)

Dr.Ruud

unread,
Feb 23, 2005, 6:27:40 PM2/23/05
to
Toen ik robert kietelde, kwam er dit uit:

> En kennelijk kost de check of een variabele in scope is of niet
> toch wel enige rekenkracht.

Aha. Ik heb het net ook maar eens uitgeprobeerd, en het gaat zelfs
nog verder: de my-variabele wordt bij elke passage opnieuw opgezet,
met waarde 0.

use strict;

my $num = 10;

my ($a, $b) = ("*A*", "*A*");
print "A: a=$a, b=$b\n";

sub inloop {
print "\n-inloop--\n";
print "{a=$a, b=$b}\n";


for (my $i = 0; $i < $num; $i++) {

my $a++;
my $b += $a;
print "{{a=$a, b=$b}}\n";
}
print "{a=$a, b=$b} !!!\n";
print "-inloop--\n";
}

my ($a, $b) = ("*B*", "*B*");
print "B: a=$a, b=$b\n";

sub outloop {
print "\n-outloop--\n";
print "{a=$a, b=$b} !!!\n";


my ($a, $b);
for (my $i = 0; $i < $num; $i++) {

$a++;
$b += $a;
print "{{a=$a, b=$b}}\n";
}
print "{a=$a, b=$b}\n";
print "-outloop--\n";
}

my ($a, $b) = ("*C*", "*C*");
print "C: a=$a, b=$b\n";

inloop();
print "a=$a, b=$b\n";

outloop();
print "a=$a, b=$b\n";


Zie ook:
http://perl.plover.com/FAQs/Namespaces.html

--
Affijn, Ruud ` - ?
+ ` ? *
? ` Jvr qvg yrrfg,
? = ` fgresg wbatre.


John Bokma

unread,
Feb 23, 2005, 10:01:30 PM2/23/05
to
Dr.Ruud wrote:

> Toen ik robert kietelde, kwam er dit uit:
>
>> En kennelijk kost de check of een variabele in scope is of niet
>> toch wel enige rekenkracht.
>
> Aha. Ik heb het net ook maar eens uitgeprobeerd, en het gaat zelfs
> nog verder: de my-variabele wordt bij elke passage opnieuw opgezet,
> met waarde 0.

undef zal je bedoelen, en ja, dat klopt :-D, sterker daar is niks mis mee.
En buiten het block waarin je ze definieert kan je ze niet meer gebruiken.

Dr.Ruud

unread,
Feb 23, 2005, 10:52:09 PM2/23/05
to
Toen ik John Bokma kietelde, kwam er dit uit:
> Dr.Ruud:
>> robert:

>>> En kennelijk kost de check of een variabele in scope is of niet
>>> toch wel enige rekenkracht.

>> Aha. Ik heb het net ook maar eens uitgeprobeerd, en het gaat zelfs
>> nog verder: de my-variabele wordt bij elke passage opnieuw opgezet,
>> met waarde 0.

> undef zal je bedoelen, en ja, dat klopt :-D, sterker daar is niks
> mis mee.

Je hebt in Perl dus een extra laag {} nodig om het 'netjes' te krijgen:
(netjes als in: de variabelen zijn na het block waarin ze gebruikt
worden, per direct niet meer beschikbaar)

{ my ($a, $b) = (0, 0);
while (busy()) {
$a++;
$b += $a;
print "$b ";
} }


Een my in de for() veroorzaakt blijkbaar iets verborgens, dus dit:

for (my $i = 0; $i < 10; $i++) { ...; }

is eigenlijk dit:

{ my $i;
for ($i = 0; $i < 10; $i++) {
...;
} }


Zie ook "Other Properties of my Variables" op die
URL:http://perl.plover.com/FAQs/Namespaces.html.

John Bokma

unread,
Feb 24, 2005, 12:48:54 AM2/24/05
to
Dr.Ruud wrote:

> Toen ik John Bokma kietelde, kwam er dit uit:
>> Dr.Ruud:
>>> robert:
>
>>>> En kennelijk kost de check of een variabele in scope is of niet
>>>> toch wel enige rekenkracht.
>
>>> Aha. Ik heb het net ook maar eens uitgeprobeerd, en het gaat zelfs
>>> nog verder: de my-variabele wordt bij elke passage opnieuw opgezet,
>>> met waarde 0.
>
>> undef zal je bedoelen, en ja, dat klopt :-D, sterker daar is niks
>> mis mee.
>
> Je hebt in Perl dus een extra laag {} nodig om het 'netjes' te
> krijgen: (netjes als in: de variabelen zijn na het block waarin ze
> gebruikt worden, per direct niet meer beschikbaar)

Dat kan, en soms zie ik dat inderdaad wel eens, a la

{
local ...
...
}

> Een my in de for() veroorzaakt blijkbaar iets verborgens, dus dit:
>
> for (my $i = 0; $i < 10; $i++) { ...; }
>
> is eigenlijk dit:
>
> { my $i;
> for ($i = 0; $i < 10; $i++) {
> ...;
> } }

Yup, en heel handig dus. Aan de andere kant, in 99 van de 100 Perl
scripts zal je geen for zien op die manier :-D.

Kees de Koster

unread,
Feb 24, 2005, 5:13:39 AM2/24/05
to
In article <newscache$hpbbci$x9d$1...@news.emea.compuware.com>, Koos Pol wrote:

[...]


>
> Met een Perl scriptje bijv.:
>
> use strict;
> use warnings;
>
> my $line;
> my ($be, $ae); # before equal sign, after equal sign
> my @numbers;
> while ($line = <DATA>) {
> ($be, $ae) = split /=/, $line;
> @numbers = split /,/, $ae;
> pop @numbers;
> @numbers = map {$_ * 4} @numbers;
> print join " ", map {"[$_]"} @numbers;
> print "\n";
> }
>

[...]

Bedankt Koos, (en alle andere natuurlijk) ik heb je voorbeeld gebruikt
om het volgende Perl progje in elkaar te frutselen.

#v+
#!/usr/bin/perl

if ($#ARGV != 2) {
print "usage: input-file output-file factor\n";
exit;
}

$inputfile = $ARGV[0];
$outputfile = $ARGV[1];
$factor = $ARGV[2];

open(IF, $inputfile);
open(OF, ">$outputfile");

my $line;
my ($bl, $el);
my @numbers;
my $volume;

while ($line = <IF>) {
($bl, $el) = split /=/, $line;
if ($bl > 19000000000000) {
@numbers = split /,/, $el;
$volume = pop @numbers;
@numbers = map {$_ * $factor} @numbers;
use integer;
$volume = $volume / $factor;
print OF $bl;
print OF "=";
print OF join "", map {"$_,"} @numbers;
print OF $volume;
print OF "\n";
} else {
print OF $line;
}
}

close(IF);
close(OF);

exit;
#v-

<INPUT>
ChartPath=/home/sircrow/Qtstalker/data/Stocks/AAB
0=Plugin=HorizontalLine|Name=0|Value=19.9431|Plot=Main Plot|Color=#0055ff
19940103000000=8.15,8.36,8.13,8.33,2893070
19940104000000=8.35,8.35,8.26,8.26,4084400
19940105000000=8.33,8.33,8.28,8.3,5622470
20050218000000=21.16,21.28,21.08,21.16,6017510
20050221000000=21.17,21.19,20.82,20.88,6842220
BarType=0
CHARTOBJECTS=0
Plugin=Stocks
Symbol=AAB
Title=AAB
Type=Stock
</INPUT>

<OUTPUT> (factor = 4)
ChartPath=/home/sircrow/Qtstalker/data/Stocks/AAB
0=Plugin=HorizontalLine|Name=0|Value=19.9431|Plot=Main Plot|Color=#0055ff
19940103000000=32.6,33.44,32.52,33.32,723267
19940104000000=33.4,33.4,33.04,33.04,1021100
19940105000000=33.32,33.32,33.12,33.2,1405617
20050218000000=84.64,85.12,84.32,84.64,1504377
20050221000000=84.68,84.76,83.28,83.52,1710555
BarType=0
CHARTOBJECTS=0
Plugin=Stocks
Symbol=AAB
Title=AAB
Type=Stock
</OUTPUT>

Er zullen wel wat niet zulk mooie constructies inzitten maar tis m'n
eerste Perl progje, ga vanmiddag naar de bieb een Perl boek zoeken.

GG
Kees
--
momentum, n.:
What you give a person when they are going away.
11:12:05 up 2 days, 1:47, 4 users, load average: 0.27, 0.07, 0.05

Koos Pol

unread,
Feb 24, 2005, 6:16:51 AM2/24/05
to
Kees de Koster wrote (Thursday 24 February 2005 11:13):

> ik heb je voorbeeld gebruikt om het volgende Perl progje in
> elkaar te frutselen.

Voor een eerste frutsel ziet het er prima uit, hoor.

> open(IF, $inputfile);
> open(OF, ">$outputfile");

open(IF, $inputfile) || die "Can't open $inputfile ($!)";
open(OF, ">$outputfile") || die "Can't open $outputfile ($!)";

Ter controle of het wel gelukt is.

> my $line;
> my ($bl, $el);
> my @numbers;
> my $volume;
>
> while ($line = <IF>) {
> ($bl, $el) = split /=/, $line;
> if ($bl > 19000000000000) {

Kan wel. Maar

if (( $bl =~ m|^\d{14}$| ) && ( $bl > 19000000000000)) {

is mooier. Dan weet je zeker dat je met een datum-getal van doen
hebt.

> @numbers = split /,/, $el;
> $volume = pop @numbers;
> @numbers = map {$_ * $factor} @numbers;
> use integer;


Kan wel. Maar mooier is een extra isolatie block. Voor de
programmeur is eea daarmee netter afgewerkt. (In dit specifieke
geval maakt het voor Perl niets uit.)

{
use integer;
...
}


> $volume = $volume / $factor;
> print OF $bl;
> print OF "=";
> print OF join "", map {"$_,"} @numbers;
> print OF $volume;
> print OF "\n";

Of in een regel natuurlijk:

print OF "$bl=".join ("", map {"$_,"} @numbers).($volume/4)."\n";

> Er zullen wel wat niet zulk mooie constructies inzitten maar tis
> m'n eerste Perl progje, ga vanmiddag naar de bieb een Perl boek
> zoeken.

"Learning Perl". Of als je't aandurft: "Programming Perl".

Succes.

Dr.Ruud

unread,
Feb 24, 2005, 8:30:21 AM2/24/05
to
Toen ik John Bokma kietelde, kwam er dit uit:
> Dr.Ruud:

>> Een my in de for() veroorzaakt blijkbaar iets verborgens, dus dit:


>>
>> for (my $i = 0; $i < 10; $i++) { ...; }
>>
>> is eigenlijk dit:
>>
>> { my $i;
>> for ($i = 0; $i < 10; $i++) {
>> ...;
>> } }

> Yup, en heel handig dus.

Ja, maar wel verhullend, want de scope van de $var die in de for()
(of in de foreach) staat, heeft dan niet de scope van de
zichtbare {} waar hij tussen staat:

use strict;

sub demo
{
foreach my $text ("A", "B", "C") {
print "text=$text\n";
}
print "text=$text\n"; # compilation-error
}

demo();


> Aan de andere kant, in 99 van de 100 Perl
> scripts zal je geen for zien op die manier :-D.

Als perl het al voor je doet, hoef je het niet zelf meer
te doen. Maar een rammelende syntax blijft het. Kan er even
iemand dit (op theoretische wijze) met C++ vergelijken?
Zoiets als:

for (int i; i < 10; i++) {
int a++;
int b += a;
cout << "a=", a, ", b=", b, '\n';
}

(ongetest)

John Bokma

unread,
Feb 24, 2005, 12:06:45 PM2/24/05
to
Dr.Ruud wrote:

> Toen ik John Bokma kietelde, kwam er dit uit:

[ snip for ( my ... ]

> Ja, maar wel verhullend, want de scope van de $var die in de for()
> (of in de foreach) staat, heeft dan niet de scope van de
> zichtbare {} waar hij tussen staat:

Dat is idem in Java, idem in C/C++, en wellicht nog in een aantal andere
talen precies hetzelfde :-D.

>> Aan de andere kant, in 99 van de 100 Perl
>> scripts zal je geen for zien op die manier :-D.
>
> Als perl het al voor je doet, hoef je het niet zelf meer
> te doen.

Ik bedoel dus een for met een index, meestal gebruik je dingen als:

for my $item ( @array ) { .. }

> Maar een rammelende syntax blijft het.

Je bedoelt het beperken van de scope of het resetten van de vars binnen de
lus?

robert

unread,
Feb 24, 2005, 12:18:00 PM2/24/05
to
John Bokma <postm...@castleamber.com>:

> Dr.Ruud wrote:
>
>> Toen ik John Bokma kietelde, kwam er dit uit:
>
> [ snip for ( my ... ]
>> Ja, maar wel verhullend, want de scope van de $var die in de for() (of
>> in de foreach) staat, heeft dan niet de scope van de zichtbare {} waar
>> hij tussen staat:
>
> Dat is idem in Java, idem in C/C++, en wellicht nog in een aantal andere
> talen precies hetzelfde :-D.

Ik heb m'n vingers wel eens gebrand aan vergelijkbare code in Javascript:
for (var i = 0; i < 10; i++) { ... }

Daarmee declareer je een variabele 'i' die binnen het blok dat de for-lus
omvat geldig is, i.t.t. Perl, Java en C/C++ waar 'i' alleen in op het
for-statement-volgende blok geldig is.

--
robert

John Bokma

unread,
Feb 24, 2005, 12:38:50 PM2/24/05
to
robert wrote:

> Ik heb m'n vingers wel eens gebrand aan vergelijkbare code in
> Javascript:
> for (var i = 0; i < 10; i++) { ... }
>
> Daarmee declareer je een variabele 'i' die binnen het blok dat de
> for-lus omvat geldig is, i.t.t. Perl, Java en C/C++ waar 'i' alleen in
> op het for-statement-volgende blok geldig is.

Auw, en schande! Ik doe mijn best om dat te onthouden, want daar zou ik ook
instinken :-(

John Bokma

unread,
Feb 24, 2005, 1:13:04 PM2/24/05
to
Kees de Koster wrote:

> #v+
> #!/usr/bin/perl

Erg belangrijk om hier direct neer te zetten:

use strict;
use warnings;

> if ($#ARGV != 2) {
> print "usage: input-file output-file factor\n";
> exit;
> }

leesbaarder:

unless ( @ARGV == 3 ) {

print ...
exit;
}

> $inputfile = $ARGV[0];
> $outputfile = $ARGV[1];
> $factor = $ARGV[2];


my ( $inputfile, $outputfile, $factor ) = @ARGV;

> open(IF, $inputfile);
or die "Can't open '$inputfile' for reading: $!";

> open(OF, ">$outputfile");

idem.

Met een recente versie van Perl kan je ook:

open my $if, $inputfile or die...
open my $of, '>', $outputfile or die ...

doen

> my $line;

stop in de while

> my ($bl, $el);

stop in de while

> my @numbers;
> my $volume;

ditto


>
> while ($line = <IF>) {
> ($bl, $el) = split /=/, $line;
> if ($bl > 19000000000000) {
> @numbers = split /,/, $el;
> $volume = pop @numbers;

while ( my $line = <$if> ) {

my ( $bl, $el ) = split /=/, $line;
unless ( $bl > 19000000000000 )

print $of $line;
next;
}

Dit is leesbaarder (vind ik), indien er niks te doen is, next.

@numbers = split /,/, $el;
$volume = pop @numbers;

Let op: $volume kan een \n bevatten, maar door
de vermenigvuldiging verderop raak je die kwijt.

> @numbers = map {$_ * $factor} @numbers;

doe ik later :-D.

> use integer;

ai, dat is vrij ticky, sterker, ik zou het ergens weer uitzetten.

> $volume = $volume / $factor;

$volume = int( $volume / $factor );

> print OF $bl;
> print OF "=";
> print OF join "", map {"$_,"} @numbers;
> print OF $volume;
> print OF "\n";

print "$bl=",
join ( ",", map { $_ * $factor } @numbers ),
",volume\n";


> } else {
> print OF $line;
> }
> }
>
> close(IF);

close $if or die "Can't close ... $!"; # [1]

> Er zullen wel wat niet zulk mooie constructies inzitten maar tis m'n
> eerste Perl progje, ga vanmiddag naar de bieb een Perl boek zoeken.

Probeer Learning Perl (O'Reilly) en Perl Cookbook (O'Reilly) te pakken
te krijgen.


[1] recent gehad dat dit echt faalde, de buffer werd door de close weg
geschreven, en .... er was geen ruimte meer op de HD :-D. Als je het
helemaal mooi wilt doen: ( print ...... ) or die ...

[2] En de Koos speciaal voor vandaag:

#!perl -spaF[=,]

next unless $F[0] > 19000000000000;
$_ = "$F[ 0 ]=" . join ',', (

map { $_ * $factor } @F[ 1..4 ]

), int( $F[ 5 ] / $factor ) . "\n"


convert.pl -factor=4 in.txt > out.txt

Dr.Ruud

unread,
Feb 24, 2005, 1:51:31 PM2/24/05
to
Toen ik John Bokma kietelde, kwam er dit uit:
> Dr.Ruud:

>> Maar een rammelende syntax blijft het.

> Je bedoelt het beperken van de scope of het resetten
> van de vars binnen de lus?

De 'implied braces'. (0 hits op google)

Kees de Koster

unread,
Feb 24, 2005, 3:16:09 PM2/24/05
to
In article <newscache$30yeci$h2e$1...@news.emea.compuware.com>, Koos Pol wrote:

[...]

>


> "Learning Perl". Of als je't aandurft: "Programming Perl".
>
> Succes.
>

De bovenstaande hadden ze niet, tis "Perl in 24 uur" geworden van
Clinton Pierce.

John en Koos bedankt voor de tips en correcties.

GG
Kees
--
Better hope you get what you want before you stop wanting it.
21:15:55 up 2 days, 11:50, 4 users, load average: 0.06, 0.18, 0.31

John Bokma

unread,
Feb 24, 2005, 3:30:40 PM2/24/05
to
Dr.Ruud wrote:

> Toen ik John Bokma kietelde, kwam er dit uit:
>> Dr.Ruud:
>
>>> Maar een rammelende syntax blijft het.
>
>> Je bedoelt het beperken van de scope of het resetten
>> van de vars binnen de lus?
>
> De 'implied braces'. (0 hits op google)

Er zijn meer talen die dat doen (Java, C, C++), dus ik zie het probleem
niet. Kwalijker (vind ik) is wat robert als voorbeeld gaf, dat de
variable ineens leeft buiten de lus, dus:

my $a;
for $a ( ... ) {}

en

for my $a ( ... ) {}

zijn dan equivalent.

Dan heb ik liever

{ my $a; for $a ( ... ) {}}

Koos Pol

unread,
Feb 24, 2005, 3:41:12 PM2/24/05
to
On woensdag 23 februari 2005 18:04 John Bokma wrote:

>> Nee, want dan haal je de my binnen de loop. En bij een loop van
>> een miljoen, wil je die er echt buiten hebben :-p
>
> Omdat?

Verkeerde lokvoer meneer Bokma. Ze willen niet bijten vandaag :-)

Sjoerd A. Schreuder

unread,
Feb 24, 2005, 6:23:15 PM2/24/05
to

Dr.Ruud wrote:
> Als perl het al voor je doet, hoef je het niet zelf meer
> te doen. Maar een rammelende syntax blijft het. Kan er even
> iemand dit (op theoretische wijze) met C++ vergelijken?
> Zoiets als:
>
> for (int i; i < 10; i++) {
> int a++;

Bovenstaande regel is geen geldig C++. "int a;" mag wel.
En indien het welk geldig C++ zou zijn: welke beginwaarde
heeft a dan?

> int b += a;

Weer geen geldig C++. "int b = expression;" mag, maar += mag niet.

> cout << "a=", a, ", b=", b, '\n';
> }

Sjoerd

Sjoerd A. Schreuder

unread,
Feb 24, 2005, 6:28:49 PM2/24/05
to
Dr.Ruud wrote:
> Toen ik John Bokma kietelde, kwam er dit uit:
>>Dr.Ruud:
>>>Een my in de for() veroorzaakt blijkbaar iets verborgens, dus dit:
>>>
>>> for (my $i = 0; $i < 10; $i++) { ...; }
>>>
>>>is eigenlijk dit:
>>>
>>> { my $i;
>>> for ($i = 0; $i < 10; $i++) {
>>> ...;
>>> } }

Het is ook zo in C++. Alleen was er in de begindagen van C++,
voor standaardisatie, ooit een andere regel in gebruik binnen
Microsoft en waarschijnlijk compileerde hun enorme codebase niet
met de nieuwe regel, dus in Visual C++ 6.0 was de oude regel nog
steeds de default.

Tegenwoordig doen de Microsoft compilers het wel volgens de C++
standaard.

>>Yup, en heel handig dus.
>
> Ja, maar wel verhullend, want de scope van de $var die in de for()
> (of in de foreach) staat, heeft dan niet de scope van de
> zichtbare {} waar hij tussen staat:

Er is sowieso geen een-op-een verband tussen de scope van
een variabele en de {} haken:

{
int a; // a nr 1
{
float a; // a nr 2
// hier is a nr 1 niet zichtbaar
// hier is b niet zichtbaar
}
int b;
}

De buitenste haken omsluiten zowel "int a;" als "int b;" maar toch
is de scope van zowel die a als de b niet hetzelfde als de {}.

Sjoerd

Dr.Ruud

unread,
Feb 24, 2005, 5:39:28 PM2/24/05
to
Toen ik John Bokma kietelde, kwam er dit uit:

> [implied braces]


> Er zijn meer talen die dat doen (Java, C, C++), dus ik zie het
> probleem niet.

Het is in zoverre een probleem dat het een uitzondering is op
de {}-structuur. Er zijn C++ compilers die er een compiler-optie
voor hebben, waarmee je dus de {}-structuur leidend maakt, net
als in JavaScript.

Uit de beschrijving van de taal moet goed blijken dat het scope-
blok niet altijd bij de start-accolade begint, maar dat er soms
iets bijzonders aan de hand is. Bij de for() geldt dat overigens
alleen voor het eerste deel, dus voor de eerste ';'

use strict;
sub init { return ($_[0] + 5); }
for (my $a = init(my $b = -1); $a <= 10; $a++) {


$b += $a;
print "a=$a, b=$b\n";
}

print "a=$a, b=$b\n"; # a en b beide unset


> Kwalijker (vind ik) is wat robert als voorbeeld gaf,
> dat de variable ineens leeft buiten de lus

Ik vind dat niet kwalijk. Het moet gewoon goed duidelijk zijn
welke conventie geldt.

Om portable code te maken, moet je dus eigenlijk

{ for (int var=0;;) {...} }

code schrijven, of eigenlijk zelfs

{ int var; for (var=0;;) {...} }

maar dat was ik niet echt van plan. Maar wat nu niet is,
kan best nog komen.

Herbruikbaarheid van mijn C/C++ code in JavaScript heb ik nooit
echt belangrijk gevonden. Mocht ik iets in JavaScript gaan maken,
dan zet ik dat extra {}-schild wel om de for/foreach/while/switch/
do-until/etc.-blokken (dat zijn er overigens te veel, de scope-
variatie is niet bij elk blok-type mogelijk) heen, met een droog
commentaartje erbij.

John Bokma

unread,
Feb 24, 2005, 7:09:02 PM2/24/05
to
Dr.Ruud wrote:

> Toen ik John Bokma kietelde, kwam er dit uit:
>
>> [implied braces]
>> Er zijn meer talen die dat doen (Java, C, C++), dus ik zie het
>> probleem niet.
>
> Het is in zoverre een probleem dat het een uitzondering is op
> de {}-structuur. Er zijn C++ compilers die er een compiler-optie
> voor hebben, waarmee je dus de {}-structuur leidend maakt, net
> als in JavaScript.
>
> Uit de beschrijving van de taal moet goed blijken dat het scope-
> blok niet altijd bij de start-accolade begint, maar dat er soms
> iets bijzonders aan de hand is.

Voor mij is het met Perl en Java duidelijk :-D.

> Bij de for() geldt dat overigens
> alleen voor het eerste deel, dus voor de eerste ';'
>
> use strict;
> sub init { return ($_[0] + 5); }
> for (my $a = init(my $b = -1); $a <= 10; $a++) {
> $b += $a;
> print "a=$a, b=$b\n";
> }
> print "a=$a, b=$b\n"; # a en b beide unset

Let op: $a en $b zijn bijzondere variabelen:

use strict;
use warnings;

for ( my $x = 0;; my $y = 3) { last }

print $x;
print $y;

vs:

use strict;
use warnings;

for ( my $a = 0;; my $b = 3) { last }

print $a;
print $b;

btw:

use strict;
use warnings;

for ( my $x = 0; $x < 2; my $y = 3) { $y++; $x++; print "$x $y\n"; }

>> Kwalijker (vind ik) is wat robert als voorbeeld gaf,
>> dat de variable ineens leeft buiten de lus
>
> Ik vind dat niet kwalijk. Het moet gewoon goed duidelijk zijn
> welke conventie geldt.

Ok, voor mij ( C, C++, Java, Perl achtergrond ) is het kwalijk :-D.

> { int var; for (var=0;;) {...} }
>
> maar dat was ik niet echt van plan. Maar wat nu niet is,
> kan best nog komen.

Yikes.

> Herbruikbaarheid van mijn C/C++ code in JavaScript heb ik nooit
> echt belangrijk gevonden.

Ik moet er niet aan denken dat ik code in taal a zo op moet zetten dat
het bijna in taal b te gebruiken is. Ik raad altijd aan om in taal a in
a te programmeren, niet b ( dus geen #define begin { en zo :-D)

Stefan Arentz

unread,
Feb 25, 2005, 6:11:39 AM2/25/05
to
"Sjoerd A. Schreuder" <sa_sch...@wanadoo.nl> writes:

...

> Het is ook zo in C++. Alleen was er in de begindagen van C++,
> voor standaardisatie, ooit een andere regel in gebruik binnen
> Microsoft en waarschijnlijk compileerde hun enorme codebase niet
> met de nieuwe regel, dus in Visual C++ 6.0 was de oude regel nog
> steeds de default.

Volgens mij was dat gewoon een bug in hun C++ preprocessor.

S.

Suzan Foster

unread,
Feb 27, 2005, 7:53:28 AM2/27/05
to
robert wrote:

> Ik heb m'n vingers wel eens gebrand aan vergelijkbare code in Javascript:
> for (var i = 0; i < 10; i++) { ... }
> > Daarmee declareer je een variabele 'i' die binnen het blok dat de for-lus
> omvat geldig is, i.t.t. Perl, Java en C/C++ waar 'i' alleen in op het
> for-statement-volgende blok geldig is.

vc++.6.0 doet het verkeerd. ik heb nogal wat code waarbij ik de i
expliciet buiten de for definieer om cross-platform te blijven. vanaf
vc++.NET is het meen ik opgelost.

groetjes, su.

0 new messages