Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: Increaing a field size for a record

by zwon (Abbot)
on Oct 16, 2012 at 12:42 UTC ( [id://999319]=note: print w/replies, xml ) Need Help??


in reply to Increaing a field size for a record

That's fairly simple. You just read the file, parse the records, and output them into a new file in a desired fashion. Then rename file and that's it. There's no magic that would allow expand field in place.

  • Comment on Re: Increaing a field size for a record

Replies are listed 'Best First'.
Re^2: Increasing a field size for a record
by Athanasius (Archbishop) on Oct 16, 2012 at 13:07 UTC
    There's no magic that would allow expand field in place.

    What? No magic? But this is Perl — of course there’s magic!

    #! perl use strict; use warnings; use Tie::File; my $filename = 'data.txt'; tie my @lines, 'Tie::File', $filename or die "Cannot tie file '$filen +ame' to array: $!"; for (my $i = 0; $i < @lines; ++$i) { my @fields = split ' ', $lines[$i]; $fields[1] .= ' ' x (50 - length $fields[1]); $lines[$i] = join(' ', @fields); } untie @lines;

    Test file “data.txt” before running the script:

    DSE 1232123456 ABCDEF96DS0 20100722 20120827KJHLK LKEDX 058305574 IAC +8 S73 WERTYU DSE 987 ABCDEF96DS0 20100722 20120827KJHLK LKEDX 058305574 IAC 8 S73 W +ERTYU DSE 12321234567890 ABCDEF96DS0 20100722 20120827KJHLK LKEDX 058305574 +IAC 8 S73 WERTYU

    and after:

    DSE 1232123456 ABCDEF96DS0 201 +00722 20120827KJHLK LKEDX 058305574 IAC 8 S73 WERTYU DSE 987 ABCDEF96DS0 201 +00722 20120827KJHLK LKEDX 058305574 IAC 8 S73 WERTYU DSE 12321234567890 ABCDEF96DS0 201 +00722 20120827KJHLK LKEDX 058305574 IAC 8 S73 WERTYU

    ;-)

    Athanasius <°(((><contra mundum

      That's a funny approach, but is not very efficient, every time you're assigning to $line[$i] it rewrites all the file starting from the record $i.

      Update: More efficient would be to use File::Slurp:

      use strict; use warnings; use File::Slurp qw(edit_file_lines); sub fix { my @fields = split / +/; $fields[1] = sprintf "%-50s", $fields[1]; $_ = join ' ', @fields; } edit_file_lines \&fix, $file_name;
      The problem is that it doesn't preserve the width of the other fields

      Hi Athanasius,

      very interesting inline approach. But is it really necessary to use this "un-perl-ish" ;-) C-construct  for (my $i = 0; $i < @lines; ++$i)? Does it also work with a foreach-loop or is then the inline editing broken?

      Best regards
      McA

        If it works and is effortless to understand ... as the original construct does and is ... then I would give it no more time than that.

        You should write your program, not only to reformat the file but also to sanity-check its own results.   For example, if you can assert that the line should contain exactly, say, 11 groups, then your program should make that assertion, and it should die if it does not.   If you can say that (especially, nearby) fields should be of a certain form that can be checked by a regex, make that check.

        The reason is that, if there is a problem either with the file or with the program ... or if there has been some subtle change such that this program’s underlying assumptions no longer hold true as-written, then no human is likely to detect the problem.   But the software is in an ideal position to do so.

        Good point! After a little experimentation, it appears that the following also works:

        for my $line (@lines) { my @fields = split ' ', $line; $fields[1] .= ' ' x (50 - length $fields[1]); $line = join(' ', @fields); }

        Thanks, nice catch!

        Athanasius <°(((><contra mundum

      Thanks Athanasius! That was really halpful I got a problem, the positions are not space separated, If I insert 39 spaces from postion 15 in all records will help.. how can I do that ?

        Hello Thomas Kennll,

        It seems you’ve re-written your original question. Please don’t do that! It makes it difficult for anyone who tries to follow the thread — besides making it very confusing for those trying to help you. See the recent posting On node obliteration.

        In a previous post you say the fields are space separated, now they’re not? Then how do you distinguish one field from the next? Also, you say you want to insert spaces “from pos[i]tion 15 in all records”, but in the data originally shown, none of the fields was more than 13 characters long. You will need to provide sample data showing the way fields are set out on each line. (And please remember to enclose the data in <code> </code> tags.)

        As for inserting spaces (or any other string) into an existing string, you can use substr, as shown by flexvault below.

        Athanasius <°(((><contra mundum

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://999319]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-04-26 07:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found