http://www.perlmonks.org?node_id=1231527

Oskym has asked for the wisdom of the Perl Monks concerning the following question:

Hi PerlMonkeys!

I'd made a simple script trying to get the final part from a line from the 4th space occurrence.

The Output should be like this:

"GetCertificate](3) Returning context. ID=PTWEBSERVER, Lang=ENG"

Instead of that I'm getting this:

"(6) 01/02/19 06:30:30 GetCertificate(3) Returning context. ID=PTWEBSERVER, Lang=ENG"

Can I ask for help to any expert?

Here is the code:

use strict; use warnings; my $line='PSAPPSRV.26476584 (6) 01/02/19 06:30:30 GetCertificate(3) Re +turning context. ID=PTWEBSERVER, Lang=ENG'; my $SpaceChar = ' '; my $offset = 0; my $result = substr $line,index($line, $SpaceChar, $offset); while ($offset < 4) { $result = substr $line,index($line, $SpaceChar, $offset); print "$result \n"; $offset++; print "offset: $offset \n"; }

Thanks for your help!!

Replies are listed 'Best First'.
Re: With substr, index the offset don't get proper start position
by hippo (Canon) on Mar 21, 2019 at 10:55 UTC

    If you really want to do it using substr and index then here is one iterative method:

    use strict; use warnings; my $line='PSAPPSRV.26476584 (6) 01/02/19 06:30:30 GetCertificate(3) Re +turning context. ID=PTWEBSERVER, Lang=ENG'; my $SpaceChar = ' '; my $result = $line; for (1..4) { $result = substr ($result, index ($result, $SpaceChar) + 1); print "$result\n"; }

    Here's a simpler one with split instead:

    #!/usr/bin/env perl use strict; use warnings; my $line='PSAPPSRV.26476584 (6) 01/02/19 06:30:30 GetCertificate(3) Re +turning context. ID=PTWEBSERVER, Lang=ENG'; my $SpaceChar = ' '; my $result = (split ($SpaceChar, $line, 5))[4]; print "$result\n";

    Update: edit of first snippet to remove expensive no-op.

Re: With substr, index the offset don't get proper start position
by talexb (Canon) on Mar 21, 2019 at 12:47 UTC

    Brother hippo's answer is fine, but it may seem a little like magic to you, so I'm adding a bit of an explanation (if you're interested).

    The split function takes a number of arguments; you can give it zero to three arguments. That information is available using perldoc -f split, or by looking the function up in whichever Perl book that you have.

    The first argument is a regular expression -- in this case, we're using a space to split the string (the second argument) into pieces using the space as the splitting point. The third argument says "Stop splitting after this many pieces, and put the remaining string into the last list element".

    So we're splitting your string into five pieces; and the last piece is whatever's after the fourth space.

    Because this is Perl, there's more than one way to do it (we even abbreviate that to TMTOWTDI, pronounced TimToady), and you can use a loop if you like -- but hippo's solution using split is more Perl-ish.

    You could even use a regular expression to capture the piece you want .. but that's left as an exercise for the student. Or someone else later on in this thread. :)

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Re: With substr, index the offset don't get proper start position
by tybalt89 (Parson) on Mar 21, 2019 at 13:03 UTC
    #!/usr/bin/perl # https://perlmonks.org/?node_id=1231527 use strict; use warnings; my $line='PSAPPSRV.26476584 (6) 01/02/19 06:30:30 GetCertificate(3) Re +turning context. ID=PTWEBSERVER, Lang=ENG'; my ($result) = $line =~ /^(?:\S* ){4}(.*)/; print "$result\n"; print "offset: $-[1]\n";
Re: With substr, index the offset don't get proper start position
by pgmer6809 (Novice) on Mar 24, 2019 at 21:43 UTC

    I think your basic error was to try to put too much into the variable offset. You are asking it to do too much. Here is a more verbose version showing which variables do what. We are not worried about shortest code here! An "experienced" Perl programmer would have used a regular expression to parse out the piece he wanted. See the last lines of the code below.

    my $line='PSAPPSRV.26476584 (6) 01/02/19 06:30:30 GetCertificate(3) Re +turning context. ID=PTWEBSERVER, Lang=ENG'; my $SpaceChar = ' '; my $offset = 0; my $start_at=0; my $space_ctr = 0; my $result; while ($space_ctr < 4) { $offset = index($line, $SpaceChar, $start_at); # $offset $result = substr $line,index($line, $SpaceChar, $start_at); $space_ctr++; $start_at = $offset + 1; print "Substr($offset) = $result \n"; print "space #:$space_ctr found at offset: $offset \n"; } # using a regex to parse out the piece we want: $line =~ m/\S*\s+\S*\s+\S*\s+\S*\s+(.*)/ ; # \S* is zero or more NON space chars. \s+ is one o +r more SPACE chars. (.*) is everything after the 4th space. saved in +$1 for later use. my $wanted_substr = $1; print "Wanted String= $wanted_substr \n"; exit 1;