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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |