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

How can I print all data between .1 and FA so that I only get c##t#d#
10 1/0/6/0/0.1.20.0.0.2.1 c10t2d1 FA I have tried print if /\B.\d+.\d+\s+.?\s+\B/; print if /\B.\d+.\d+\s+.?\s+\B/FA; print if /\B.\d+\s+\w+\B/FA;
thx!

Replies are listed 'Best First'.
Re: boundries \b \B
by johngg (Canon) on Jun 14, 2010 at 20:39 UTC

    Another way would be to use split.

    $ perl -E ' > $data = q{10 1/0/6/0/0.1.20.0.0.2.1 c10t2d1 FA}; > $dev = ( split m{\s+}, $data )[ 2 ]; > say $dev;' c10t2d1 $

    I hope this is helpful.

    Cheers,

    JohnGG

      I liked JohnGG's split idea. This is a fine way to go when the data is white-space separated.

      I would just point out that it is also possible to specify an index from the end of the array for the list slice. Instead of saying "2" which means skip 0 and 1, you can say -2 which means next to last in the array, [-1] is the last thing in the array (FA). Sometimes this helps if there is a lot of things on the line or if number of things varies. Here 2 and -2 mean the same thing and is just a coincidence.

      If this c,t,d fields are always there, then extracting the digits is easy with match global:

      my $dev = "c10t2d1"; my($c,$t,$d) = $dev =~ m/\d+/g; print "$c $t $d"; #prints: 10 2 1
      If you need a regex, say line can end in other things than FA, then one way is anchor the regex to the end of the line and "work backwards", one way:
      my $test = "10 1/0/6/0/0.1.20.0.0.2.1 c10t2d1 FA "; my ($ctd) = $test =~ m/(\w+)\s+FA\s*$/; print $ctd; #prints: c10t2d1
Re: boundries \b \B
by jwkrahn (Abbot) on Jun 14, 2010 at 22:45 UTC

    \b will match between a \w character and a \W character and \B will match between two \w characters or between two \W characters.

    I have tried print if /\B.\d+.\d+\s+.?\s+\B/; print if /\B.\d+.\d+\s+.?\s+\B/FA; print if /\B.\d+\s+\w+\B/FA;

    Your examples start off with \B.\d+ which says match at a \B boundary then match any character (except newline) then match one or more digits.    So if the any character before the digits is a \w character then there must be at least two \w characters before the digits or if the any character before the digits is a \W character then there must be at least two \W characters before the digits.

    The only strings in your example that will match that pattern are "c10" or "0t2" or "2d1".

Re: boundries \b \B
by davido (Cardinal) on Jun 14, 2010 at 21:08 UTC

    In your question, are you using '#' as wildcards? Does that mean that c, t, and d will always be present in a suitable match? Will there always be whitespace on either side of a suitable capture? If so:

    if( $_ =~ m/\s(c\d+t\d+d\d+)\s/ ) { print $1; }

    Dave

Re: boundries \b \B
by choroba (Cardinal) on Jun 14, 2010 at 20:31 UTC
    If you really want to print what is between .1 and FA, you can try something like the following:
    print $1 if /\.1\s+(.*?)\s+FA/;