Regex on Perl to capture this type of value (a)(2)

Viewed 105

I'm working on perl to capture this this part of the HTML file so for example:

I'm using this regex ([0-9]{4}).([0-9]{4}) to capture this 1910.1024. But some portion of the HTML file have this kind of value 1910.1024(a)(2). I don't know the proper way to captured this two parentheses with a value inside it. I will be using this regex to my Perl script to substitute this a link.

My script now is capturing this value 1910.1024, I want to know on how to captured this 1910.1024(a)(2) one.

if($content =~ m/([0-9]{4}).([0-9]{4})/gm){
   $content =~ s/([0-9]{4}).([0-9]{4})/<!!uf dp_ecfr29 29cfr$1x$2 #29cfr$1x$2>$1.$2<\/a>/gm;
}
elsif($content2 =~ m/([0-9]{4})\.([0-9]{4})(?:\((\w+)\))?(?:\((\w+)\))/gm){
   $content2 =~ s~([0-9]{4})\.([0-9]{4})(?:\((\w+)\))?(?:\((\w+)\))?~<!!uf dp_ecfr29 29cfr$1x$2 #29cfr$1x$2z-$3-$4>$1.$2($3)($4)</a>~g; 
}
elsif($content3 =~ m/([0-9]{4})\.([0-9]{4})(?:\((\w+)\))/gm){
   $content3 =~ s~([0-9]{4})\.([0-9]{4})(?:\((\w+)\))?~<!!uf dp_ecfr29 29cfr$1x$2 #29cfr$1x$2z-$3>$1.$2($3)</a>~g; 
} 
else {
   printf "Error";
}
1 Answers

You can use a couple of optional capturing groups in the regex pattern and then a couple of conditions in the replacement part.

As the regex is quite long, you may use the /x flag to break it on separate lines.

See the Perl demo:

#!/usr/bin/perl
use feature "say";
use strict;
use warnings;

my $content = "I am trying to capture this 1910.1024,  this 1910.1024(a) and  this 1910.1024(a)(3).";
if($content =~ m/([0-9]{4})\.([0-9]{4})/) {
   $content =~ s{
        ([0-9]{4})      # $1 = First 4 digits
        \.              # Dot
        ([0-9]{4})      # $2 = Second 4 digits
        (?:\((\w+)\))?  # (, $3 (first optional "word"), )
        (?:\((\w+)\))?  # (, $4 (second optional "word"), )
    }{
        "<!!uf dp_ecfr29 29cfr$1x$2 #29cfr$1x$2" .
        (defined($3) ? "z-$3" : "") . (defined($4) ? "-$4" : "") .
        ">$1.$2" . 
        (defined($3) ? "($3)" : "") . (defined($4) ? "($4)" : "") . 
        "</a>"
    }gxe;
    say "$content\n";
} else {
   say "Error";
}

Output:

I am trying to capture this <!!uf dp_ecfr29 29cfr1910x1024 #29cfr1910x1024>1910.1024</a>,  this <!!uf dp_ecfr29 29cfr1910x1024 #29cfr1910x1024z-a>1910.1024(a)</a> and  this <!!uf dp_ecfr29 29cfr1910x1024 #29cfr1910x1024z-a-3>1910.1024(a)(3)</a>.

See the gxe, x helps break the pattern into multiple lines and add comments, g matches all occurrences in the string and e helps intepret the RHS as a Perl expression where we can introduce custom replacing logic.

Constructions like (defined($3) ? "z-$3" : "") check if Group 3 matched, and then use one replacement text or another.

Related