references to filehandle?

Discussion in 'Perl Misc' started by Stefan H., Sep 27, 2004.

  1. Stefan H.

    Stefan H. Guest

    the first field of my data is the _name_ of the measure.

    I need to create from the big file one file per measure containing only
    data from that measure. The name of each file must be the same of
    measure: ie

    bigfile.csv
    123 rms 12 132
    2312 qrt 12 231
    2342 sse 12 231

    rms.csv
    123 rms 12 132

    qrt.csv
    2342 sse 12 231

    the measure names are changing in name and number, then I cannot code
    it. I'd like to do

    sub split_measures {

    my (%splits);

    for (<MYFILE>) {
    $splits{[split /;/]->[1]} = '';
    }

    for (keys %splits) {
    open $_, ">$_.csv";
    }

    for (<MYFILE>) {
    print [split /;/;]->1 $_;
    }

    the error I get is that "strict refs" doesn't permit that. Why? It's
    safe to remove that clause? Is there a better way to do that?


    Thanks
    Stefan
    Stefan H., Sep 27, 2004
    #1
    1. Advertising

  2. Stefan H. <> wrote in
    news::

    > the first field of my data is the _name_ of the measure.


    Actually, looking at the lines below, it looks like the second field is the
    name of the measure, whatever that might mean.
    >
    > I need to create from the big file one file per measure containing only
    > data from that measure. The name of each file must be the same of
    > measure: ie
    >
    > bigfile.csv
    > 123 rms 12 132
    > 2312 qrt 12 231
    > 2342 sse 12 231
    >
    > rms.csv
    > 123 rms 12 132
    >
    > qrt.csv
    > 2342 sse 12 231
    >
    > the measure names are changing in name and number, then I cannot code
    > it. I'd like to do
    >
    > sub split_measures {
    >
    > my (%splits);
    >
    > for (<MYFILE>) {
    > $splits{[split /;/]->[1]} = '';
    > }


    Ahem ... I do not see anything that is separated using ;

    >
    > for (keys %splits) {
    > open $_, ">$_.csv";
    > }
    >
    > for (<MYFILE>) {
    > print [split /;/;]->1 $_;
    > }


    Whoa!

    D:\Home\test> perl -c s.pl
    Number found where operator expected at s.pl line 14, near "->1"
    (Missing operator before 1?)
    Scalar found where operator expected at s.pl line 14, near "1 $_"
    (Missing operator before $_?)
    syntax error at s.pl line 14, near "/;/;"
    Missing right curly or square bracket at s.pl line 17, at end of line
    s.pl had compilation errors.

    Did you actually run this thing? You should always post a short, self-
    contained script others can run to see what is going on.

    > the error I get is that "strict refs" doesn't permit that. Why? It's
    > safe to remove that clause? Is there a better way to do that?


    This is how I might do it:

    use strict;
    use warnings;

    while(<DATA>) {
    chomp;
    if(my @fields = /^\s*(\d+)\s+(\w+)\s+(\d+)\s+(\d+)\s*$/) {
    # Using '>>' so as to account for multiple
    # lines for a given measure
    if(open my $out, '>>', "$fields[1].csv") {
    print $out "@{[ join ';', @fields ]}\n";
    } else {
    warn "Cannot open $fields[1].csv: $!";
    }
    }
    }

    __DATA__
    123 rms 12 132
    2312 qrt 12 231
    2342 sse 12 231

    __END__

    Sinan.
    A. Sinan Unur, Sep 27, 2004
    #2
    1. Advertising

  3. Stefan H.

    Stefan H. Guest

    On 27 Sep 2004 03:29:11 GMT, "A. Sinan Unur" <>
    wrote:

    >Ahem ... I do not see anything that is separated using ;


    sorry, I forgot to mention that the data files are semicolon separated
    file

    > print $out "@{[ join ';', @fields ]}\n";
    > } else {
    > warn "Cannot open $fields[1].csv: $!";


    you don't close the open filehandles. Is this ok?

    Thank you very much.

    A curiosity:

    my code

    for (<MYFILE>) {
    $splits{[split /;/]->[1]} = '';
    }

    for (keys %splits) {
    open $_, ">$_.csv";
    }

    was totally wrong? I mean: is it not possible to open filehandles using
    scalar variables like that?

    And:
    $splits{[split /;/]->[1]} = '';

    is it correct?

    Thank you again
    Stefan
    Stefan H., Sep 27, 2004
    #3
  4. Stefan H.

    Joe Smith Guest

    Stefan H. wrote:

    > for (keys %splits) {
    > open $_, ">$_.csv";
    > }
    >
    > was totally wrong? I mean: is it not possible to open filehandles using
    > scalar variables like that?


    Use a hash to store lexical file handles. Also use 3-argument open().

    my %fh; # Hash of file handles
    for (keys %splits) {
    open {$fh{$_}},'>>',"$_.csv";
    }
    ...
    $name = $fields[1];
    print {$fh{$name}} $_;

    -Joe
    Joe Smith, Sep 27, 2004
    #4
  5. On Mon, 27 Sep 2004 02:47:38 GMT, Stefan H. <>
    wrote:

    >I need to create from the big file one file per measure containing only
    >data from that measure. The name of each file must be the same of
    >measure: ie
    >
    >bigfile.csv
    >123 rms 12 132
    >2312 qrt 12 231
    >2342 sse 12 231
    >
    >rms.csv
    >123 rms 12 132


    I see *basically* two possible approaches:

    1. One-pass, repeatedly open()ing and close()ing FHs in '>>' mode,
    2. Two-pass, collecting the data and printing it out later.

    If bigfile is not really *too big* I'd favour the second solution.

    > for (<MYFILE>) {
    > $splits{[split /;/]->[1]} = '';

    ^^^
    ^^^

    I assume that fields are really semicolon separated rather than
    whitespace separated, so (2) above *could* be something like this:


    #!/usr/bin/perl

    use strict;
    use warnings;

    my %data;
    while (<>) {
    my $m=(split /;/)[1] or
    warn("Possibly wrong format!"), next;
    $m .= '.csv';
    push @{ $data{$m} }, $_;
    }

    for (keys %data) {
    open my $fh, '>', $_ or
    die "Can't write to `$_': $!\n";
    print $fh @{ $data{$_} };
    }

    __END__


    Of course you could/should add finer checks according to how your real
    data looks like, e.g.

    (my $n=(split /;/)[1]) =~ /^[a-z]{3}$/ or # ...

    > for (keys %splits) {
    > open $_, ">$_.csv";
    > }


    Actually you can't do this, you may at most open a lexical FH and
    store it in a hash as a value corresponding to $_.

    >for (<MYFILE>) {
    > print [split /;/;]->1 $_;

    ^^^
    ^^^

    Are you sure? ;-)

    As a side note it doesn't really do any harm but it is not necessary
    to create an anonymous array to dereference it soon after:

    (split /;/)[1]

    will do!

    >the error I get is that "strict refs" doesn't permit that. Why? It's
    >safe to remove that clause? Is there a better way to do that?


    There are many better ways to do that. However now I understand what
    you *wanted* to do. Indeed it suggests a viable "mixed" solution in
    one pass by means of an orkish manouvre:


    #!/usr/bin/perl

    use strict;
    use warnings;

    my %fh;
    while (<>) {
    my $m=(split /;/)[1] or
    warn("Possibly wrong format!"), next;
    $m .= '.csv';
    select $fh{$m} ||= do {
    open my $fh, '>', $m or
    die "Can't write to `$_': $!\n";
    $fh;
    };
    print;
    }

    __END__


    Here the possible problem is that depending on how many measures you
    really have, you could hit the maximum number of open files your OS
    permits...


    HTH,
    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 27, 2004
    #5
  6. Sorry, I hadn't read Sinan Unur's reply yet when posting my own...


    On Mon, 27 Sep 2004 06:35:51 GMT, Stefan H. <>
    wrote:

    >> print $out "@{[ join ';', @fields ]}\n";

    ^^^^
    ^^^^

    >you don't close the open filehandles. Is this ok?


    Yes it is. In fact he's using a lexical FH: it will be automatically
    closed when going out of scope (or more generally whene there will
    remain no references to it).

    >Thank you very much.
    >
    >A curiosity:
    >
    >my code

    [snip]
    >was totally wrong? I mean: is it not possible to open filehandles using
    >scalar variables like that?


    It is possible to open FHs using scalar variables. But not *like
    that*. For another cmt on your approach, slightly revised, see my
    other post in this thread.

    >And:
    >$splits{[split /;/]->[1]} = '';
    >
    >is it correct?


    This is syntactically correct. But then again see my other post for a
    cmt on this line...


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 27, 2004
    #6
  7. "A. Sinan Unur" <> wrote in
    news:Xns9570EF19DAC7Dasu1cornelledu@132.236.56.8:

    > if(my @fields = /^\s*(\d+)\s+(\w+)\s+(\d+)\s+(\d+)\s*$/) {


    Actually, that should be

    if((my @fields = /^\s*(\d+)\s+(\w+)\s+(\d+)\s+(\d+)\s*$/) == 4) {

    Sorry, late night post.

    Sinan.
    A. Sinan Unur, Sep 27, 2004
    #7
  8. Stefan H. <> wrote in
    news::

    > On 27 Sep 2004 03:29:11 GMT, "A. Sinan Unur" <>
    > wrote:
    >
    >>Ahem ... I do not see anything that is separated using ;

    >
    > sorry, I forgot to mention that the data files are semicolon separated
    > file


    Well, it looks like you should also read the posting guidelines posted here
    frequently. The code you posted was not runnable and the data you posted
    was not real. That is not nice.

    >> print $out "@{[ join ';', @fields ]}\n";
    >> } else {
    >> warn "Cannot open $fields[1].csv: $!";

    >
    > you don't close the open filehandles. Is this ok?


    THe original code was:

    >> if(open my $out, '>>', "$fields[1].csv") {
    >> print $out "@{[ join ';', @fields ]}\n";


    I know Michele has already responded to this but here's my two cents.

    The crucial part is that the file is opened using open my $out, i.e. the
    scope of $out is limited to the if-block. $out is a lexical filehandle.
    Lexical filehandles are automatically closed upon going out of scope. On
    the other hand, you can also explicitly close them. In fact, that would be
    the only way to catch a failure on close.

    Sinan.
    A. Sinan Unur, Sep 27, 2004
    #8
  9. On Mon, 27 Sep 2004 14:02:31 +0200, Michele Dondi
    <> wrote:

    > open my $fh, '>', $m or
    > die "Can't write to `$_': $!\n";


    Sorry, this should be

    open my $fh, '>', $m or
    die "Can't write to `$m': $!\n";

    of course.


    Hope there are no more typos left,
    Michele
    --
    #!/usr/bin/perl -lp
    BEGIN{*ARGV=do{open $_,q,<,,\$/;$_}}s z^z seek DATA,11,$[;($,
    =ucfirst<DATA>)=~s x .*x q^~ZEX69l^^q,^2$;][@,xe.$, zex,s e1e
    q 1~BEER XX1^q~4761rA67thb ~eex ,s aba m,P..,,substr$&,$.,age
    __END__
    Michele Dondi, Sep 27, 2004
    #9
  10. Michele Dondi <> wrote in
    news::

    > open my $fh, '>', $m or
    > die "Can't write to `$m': $!\n";
    >
    > of course.
    >
    >
    > Hope there are no more typos left,


    Strictly speaking, not a typo, but I am going to suggest dropping the \n
    from the error message.

    Sinan.
    A. Sinan Unur, Sep 27, 2004
    #10
  11. On 27 Sep 2004 13:41:22 GMT, "A. Sinan Unur"
    <> wrote:

    >> open my $fh, '>', $m or
    >> die "Can't write to `$m': $!\n";

    [snip]
    >> Hope there are no more typos left,

    >
    >Strictly speaking, not a typo, but I am going to suggest dropping the \n
    >from the error message.


    Hehe! Opinions tend to vary here... IMHO the user should not be
    interested in the additional info that omitting \n supplies, and I
    find that generally this is the case. Well in this case, he/she may be
    interested in the line of input that triggered it, but hopefully
    knowing "which $m" is the guilty one should be enough. OTOH you should
    have noticed that my code contained also a \n-less warn() because in
    that case it seemed to mo more meaningful to do so...


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 27, 2004
    #11
  12. Stefan H.

    Abhinav Guest

    Michele Dondi wrote:
    > On 27 Sep 2004 13:41:22 GMT, "A. Sinan Unur"
    > <> wrote:
    >
    >
    >>> open my $fh, '>', $m or
    >>> die "Can't write to `$m': $!\n";

    >
    > [snip]
    >
    >>>Hope there are no more typos left,

    >>
    >>Strictly speaking, not a typo, but I am going to suggest dropping the \n

    >
    >>from the error message.

    >
    > Hehe! Opinions tend to vary here... IMHO the user should not be
    > interested in the additional info that omitting \n supplies, and I
    > find that generally this is the case. Well in this case, he/she may be
    > interested in the line of input that triggered it, but hopefully
    > knowing "which $m" is the guilty one should be enough. OTOH you should
    > have noticed that my code contained also a \n-less warn() because in
    > that case it seemed to mo more meaningful to do so...
    >


    That was interesting behaviour(for me..). Where can I find more about this ?

    Regards
    Abhinav
    Abhinav, Sep 28, 2004
    #12
  13. Abhinav <> wrote:
    > Michele Dondi wrote:
    >> On 27 Sep 2004 13:41:22 GMT, "A. Sinan Unur"
    >> <> wrote:
    >>
    >>
    >>>> open my $fh, '>', $m or
    >>>> die "Can't write to `$m': $!\n";


    >>>I am going to suggest dropping the \n
    >>>from the error message.

    >>
    >> Hehe! Opinions tend to vary here... IMHO the user should not be
    >> interested in the additional info that omitting \n supplies,



    > That was interesting behaviour(for me..). Where can I find more about this ?



    If you are interested in the die() function, an offbeat place to
    look might be the documentation for the die() function...

    perldoc -f die

    Please stop asking hundreds of people around the world to read
    the docs to you, simply read them yourself and post only if you
    still have questions after that.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Sep 28, 2004
    #13
  14. Stefan H.

    Abhinav Guest

    Tad McClellan wrote:
    [SNIP]
    > Please stop asking hundreds of people around the world to read
    > the docs to you, simply read them yourself and post only if you
    > still have questions after that.
    >
    >


    I am sorry I asked an obviously inane question like that. Won't happen again.

    Thanks
    Abhinav

    --
    Abhinav, Sep 29, 2004
    #14
  15. On Tue, 28 Sep 2004 20:01:46 +0530, Abhinav
    <> wrote:

    >> knowing "which $m" is the guilty one should be enough. OTOH you should
    >> have noticed that my code contained also a \n-less warn() because in
    >> that case it seemed to mo more meaningful to do so...

    >
    >That was interesting behaviour(for me..). Where can I find more about this ?


    perldoc -f die


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 29, 2004
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roger Leigh
    Replies:
    8
    Views:
    418
    Karl Heinz Buchegger
    Nov 17, 2003
  2. Replies:
    3
    Views:
    437
    Victor Bazarov
    Nov 10, 2004
  3. DanielEKFA
    Replies:
    8
    Views:
    590
    DanielEKFA
    May 16, 2005
  4. Replies:
    8
    Views:
    696
    Bruno Desthuilliers
    Dec 12, 2006
  5. Lars Willich
    Replies:
    13
    Views:
    821
    Ian Shef
    Oct 23, 2007
Loading...

Share This Page