ssr1012
ssr1012

Reputation: 2589

List of elements in array needs to check each one in a string

I have a *TEX file contains:

__DATA__
"\left({H^1}, \int {H^2}\right)"
"\left({H^1},\bigoplus{H^2}\right)"
"\left({H^1},{H^2}\right)"
"\left({H^1}, \bigvee {H^2}\right)"

The above *TEX contents I have to check the list of array elements which I have listed below: If any one the elements is matched then retain the line as it is: If no one of the elements matched then I need to replace \left( into ( and \right) into ).

My Arrays:

int frac prod sum oint bigvee bigcup bigcap bigoplus bigotimes

Expected Output:

"\left({H^1}, \int {H^2}\right)"
"\left({H^1},\bigoplus{H^2}\right)"
"({H^1},{H^2})"
"\left({H^1}, \bigvee {H^2}\right)"

What I have tried:

my @mathenv = qw(int frac prod sum oint bigvee bigcup bigcap bigoplus bigotimes);

while(<DATA>) {  $mathchk .= $_;  }

$boolChk = 'False';
$mathchk=~s#\\left\(((?:(?!\\(?:left|right)).)*)\\right\)# my $fulcnt=$&; my $Content=$1;
foreach my $singlemath(@mathenv)
{
    \#print "S: -$singlemath-\n";
    if($fulcnt=~m/\\$singlemath/gi)
    {  $boolChk = 'True';  }
}
print ": $boolChk \t$fulcnt\n"; system 'pause'; 
if($boolChk eq 'True') {   }
if($boolChk eq 'False') {  $fulcnt = "\($Content\)";  }
($fulcnt);
#esg;

#print $mathchk;

__DATA__
"\left({H^1}, \int {H^2}\right)"
"\left({H^1},\bigoplus{H^2}\right)"
"\left({H^1},{H^2}\right)"
"\left({H^1}, \bigvee {H^2}\right)"

I couldn't able to get the correct output hence if someone guide me where I have to modify the above code. Thanks in advance.

Upvotes: 1

Views: 83

Answers (1)

zdim
zdim

Reputation: 66873

For the shown data

use warnings;
use strict;

use List::Util qw(none);

my @terms = qw(int frac prod sum oint bigvee bigcup bigcap bigoplus bigotimes);

my ($paren_L, $paren_R) = map { quotemeta $_ } '\left(', '\right)';

while (my $line = <DATA>)
{
    if (none { $line =~ /$_/ } @terms) 
    {   
        $line =~ s|$paren_L|(|; 
        $line =~ s|$paren_R|)|;
    }
    print $line;
}

__DATA__
"\left({H^1}, \int {H^2}\right)"
"\left({H^1},\bigoplus{H^2}\right)"
"\left({H^1},{H^2}\right)"
"\left({H^1}, \bigvee {H^2}\right)"

with output

"\left({H^1}, \int {H^2}\right)"
"\left({H^1},\bigoplus{H^2}\right)"
"({H^1},{H^2})"
"\left({H^1}, \bigvee {H^2}\right)"

Notes.

  • This doesn't account for multiple bracketed expressions on a single line

  • There are (many) other ways to specify parens in Latex (\big(, \Bigg( etc).

On the other hand, the shown data is reasonable in a Latex document.

This goes over the line multiple times but is far more flexible than a single regex.


With such simple patterns we need not start the regex engine for each term, but can instead build one pattern with alternations. Substitutions can also be done in one pass, using named capture groups

my $re_terms = '(?:' . join('|', @terms) . ')';

while (my $line = <DATA>) 
{
    if ($line !~ /$re_terms/)
    {   
        $line =~ s/(?<L>$paren_L)|(?<R>$paren_R)/$+{L} ? '(' : ')'/eg;
    }   
    print $line;
}

which produces the same output.

This does expect data in the shown format: parens always paired, one set on a line.

Upvotes: 1

Related Questions