Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Locate char in a string

by tilly (Archbishop)
on Aug 05, 2000 at 07:15 UTC ( [id://26313]=CUFP: print w/replies, xml ) Need Help??

I ran across this while I was trying to locate the spaces in a row of dashes in a header line to find the placement of the columns in a formatted text report. Note that I could not just use a split in the body of the report because some entries were missing, and I had to do this for a lot of reports so I needed the process to be dynamic.

The result shows why it is good to know what /g does in scalar mode, and why pos() is a nice function to have.

This builds an array of the locations right after the space. This was perfect for me since I wanted to know where the next column would begin, but that is not always the ideal choice.

my @pos; while ($line =~ / /g) { push @pos, pos($line); }

Replies are listed 'Best First'.
(meonkeys: can't get every column)
by meonkeys (Chaplain) on Aug 06, 2000 at 00:06 UTC
    I'm having trouble getting your snippet to work. I implemented it as follows:
    #!/usr/bin/perl -w use strict; my @pos; while (<>) { m/\s+/g; push @pos, pos(); } print @pos;

    On this data file
    ------- ------------- -------- ---------- -------------

    But it only returns "8". How do I continue finding spaces?
      A /g RE in scalar context matches only once, starting from whatever pos() says it last finished at, and sets pos() of the variable appropriately. Its return is true iff it matched.

      That is why my example used it in a looping construct. Otherwise you only get the first match.

      BEGIN EDIT

      I was asked exactly what that would look like. Here it is:

      #!/usr/bin/perl -w use strict; while (<>) { my @pos; while (m/\s+/g) { # Loop while it matches push @pos, pos(); } print join " ", @pos; print "\n"; }
      END EDIT

      Note that this idea can be used to create rather complex parsing engines, each /g match being used to locate the next expected token that you are looking for. If you want to do this then you will need to be careful in how you pass the variable around. Specifically be aware of the fact that if pos($foo) is set then $bar=$foo does not result in pos($bar) being set. (But if you pass $foo into a function then pos($_[0]) will still be set.)

      This is all explained in perlop. The return of a matching operation depends on whether you are in list or scalar context, and whether or not you have /g. All 4 combinations have different behaviour, and I have found occasion to use them all. :-)

      Enjoy,
      Ben

        A thousand thanks. You helped me understand exactly what's going on here; you reminded me why I love this site/language! I shall repay you with a vote tomorrow. This works with your version:
        #!/usr/bin/perl -w use strict; my @pos; my $line = "--------- --------- -------------- ---"; while ($line =~ / /g) { push @pos, pos($line); } print @pos;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-04-19 09:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found