-1

I'm trying to build a regex which gets the following string:

Invalid version of perl: 5.8.7

Format:

Invalid version of _: _

I was wondering if is possible to get the language name and the version in one line, something like: my ($language,$version) =~ /.../.

So the output will be:

$language = perl
$version = 5.8.7

Maybe it can be done with an if-else?

TTaJTa4
  • 810
  • 1
  • 8
  • 22
  • 3
    This is a basic regex. One solution : `my ($language,$version) = ( "Invalid version of perl: 5.8.7" =~ /Invalid version of (.*): (.*)/ );` – GMB Feb 01 '19 at 01:13
  • 2
    @GMB There is no reason for parenthesis around the matching (`=~`) expression in that statement: `my ($m1, $m2) = $string =~ /($p1)($p2)/;` returns both captures (or `undef` for unmatched patterns), the list context being provided by the LHS. For matching a pattern repeatedly in a string we'd need `/g` as well. (Unless you meant the parens for emphasis?). – zdim Feb 01 '19 at 03:23
  • 3
    I suggest to start using documentation. For regex the tutorial is [perlretut](https://perldoc.perl.org/perlretut.html), and what you asked here (and half guessed) is spelled out in ["_Extracting matches_"](https://perldoc.perl.org/perlretut.html#Extracting-matches) – zdim Feb 01 '19 at 03:29
  • Possible duplicate of [Learning Regular Expressions](https://stackoverflow.com/questions/4736/learning-regular-expressions) – Biffen Feb 01 '19 at 09:08

2 Answers2

2

This is basic regex'ing, so please do read e.g. perlretut or "Mastering Regular Expressions" by Jeffrey E.F. Friedl.

TMTOWDTI of course, but here is one of them:

#!/usr/bin/perl
use strict;
use warnings;

my $input = "Invalid version of perl: 5.8.7";

my($language, $version) = ($input =~ /(\w+):\s+(\d+(?:\.\d+)*)/)
    or die "Can't detect language or version!\n";

print "'${language}' '${version}'\n";

exit 0;

Output

$ perl dummy.pl
'perl' '5.8.7'
Stefan Becker
  • 5,695
  • 9
  • 20
  • 30
  • 2
    Putting those unnecessary `{` and `}` in your print statement is likely to confuse people who are new to the language (as this poster seems to be). – Dave Cross Feb 01 '19 at 08:50
  • @DaveCross that might be, but it is one of my "best practices" for shell & perl. – Stefan Becker Feb 01 '19 at 08:58
0

You can extract multiple values from a string using "capturing". The basic version works like this. You capture text in a matched regex by surrounding the text with (...). I this example, we'll extract runs of non-whitespace characters either side of ": ".

use feature 'say'; # for "say()"

$_ = 'Invalid version of perl: 5.8.7';

if (/(\S+): (\S+)/) {
  say "Language = $1";
  say "Version  = $2";
}

The captured text is put into variables called $1 and $2. Notice that we put the whole match in an if statement to ensure that our regex matches before displaying anything.

An alternative approach which makes your code easier to understand is to copy the matching data into named variables like this:

use feature 'say'; # for "say()"

$_ = 'Invalid version of perl: 5.8.7';

if (my ($language, $version) = /(\S+): (\S+)/) {
  say "Language = $language";
  say "Version  = $version";
}

As others have pointed out, the Perl documentation is well worth reading if you're new to the language. In this case, you should spend an hour or two studying perlretut.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97