packydermic:

If you'll be doing a lot of this type of work, you'll probably do well to write an equation parser to parse the expression. Then you can do a replacement of the variables, and then write the results. (For parsing, see Parse::RecDescent or Marpa::R2. The example code for both includes the start of a basic expression parser.)

Having said that, you can definitely hack something together. I wouldn't try it the way you're going about it because dealing with parenthesis is rather difficult (at least to me) in regular expressions. Instead, I'd try something to consume your input expression chunk by chunk and build a new expression. Something like this:

#!/usr/bin/perl use strict; use warnings; my %replace = ( x=>"xSS*exp", y=>"ySS*exp", c=>"cSS*exp", k=>"kSS*exp", a=>"aSS*exp", h=>"hSS*exp", ); while (<DATA>) { s/\s+$//; print $_, " --> ", plonk($_), "\n"; } sub plonk { my $exp = shift; my $rv = ""; my @stack; while (length($exp)) { my ($var, $rest); if ($exp =~ /^(\w+)(.*)$/) { ($var, $rest) = ($1, $2); $var = $replace{$var} if exists $replace{$var}; $rv .= $var; } else { ($var, $rest) = ( substr($exp,0,1), substr($exp,1) ); if ($var eq '(') { push @stack, $rv; $rv = ""; } elsif ($var eq ')') { $rv = (pop @stack) . "($rv)"; } else { $rv .= $var; } } $exp = $rest; } return $rv; } __DATA__ y = a*(k(-1)^alpha)*(h^(1-alpha)) c*theta*hˆ(1+psi)=(1-alpha)*y 1 = beta*(c/c(+1)*alpha*y(+1)/k+(1-delta)) y = a*(k(-1)ˆalpha)*(hˆ(1-alpha)) k = y-c+(1-delta)*k(-1) ln(a) = rho*ln(a(-1))+ e

This gives:

$ perl plonk.pl y = a*(k(-1)^alpha)*(h^(1-alpha)) --> ySS*exp = aSS*exp*(kSS*exp(-1)^a +lpha)*(hSS*exp^(1-alpha)) c*theta*hˆ(1+psi)=(1-alpha)*y --> cSS*exp*theta*hSS*expˆ(1+psi)=(1-alp +ha)*ySS*exp 1 = beta*(c/c(+1)*alpha*y(+1)/k+(1-delta)) --> 1 = beta*(cSS*exp/cSS*e +xp(+1)*alpha*ySS*exp(+1)/kSS*exp+(1-delta)) y = a*(k(-1)ˆalpha)*(hˆ(1-alpha)) --> ySS*exp = aSS*exp*(kSS*exp(-1)ˆa +lpha)*(hSS*expˆ(1-alpha)) k = y-c+(1-delta)*k(-1) --> kSS*exp = ySS*exp-cSS*exp+(1-delta)*kSS*ex +p(-1) ln(a) = rho*ln(a(-1))+ e --> ln(aSS*exp) = rho*ln(aSS*exp(-1))+ e

This has some obvious problems: First, it generates gibberish if the input isn't formed correctly. Second, bare variables have the same replacement as function calls. If you need to handle that, you'll have to add some special case handling for it. There may also be some other special cases you would need to handle. But it serves well enough as a demonstration.

...roboticus

When your only tool is a hammer, all problems look like your thumb.


In reply to Re: Help with regex - find captured pattern twice by roboticus
in thread Help with regex - find captured pattern twice by pachydermic

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.