Want to substitute multiplication symbol "*" with "tensor", and the power symbol "^" with "p_tensor" using following substitution rules:
a(k)^n --> p_tensor(n,a(k))
a(i)*a(j) --> tensor(a(i),a(j)), when i=/=j
But when the symbol "*" is between a number and a(i), such as 3*a(i), we should keep the symbol "*" as what it is.
so for example,
5*a(i)*a(j)*(a(k1)+3*a(k2)) --> 5*tensor(tensor(a(i),a(j)),a(k1)+3*a(k2))
a(i)^2*a(j)^2 --> tensor(p_tensor(2,a(i)),p_tensor(2,a(j)))
...
Now I want to reformat the following expression using AWK or sed or Perl:
3*a(3)^2+6*a(1)^2*(5*a(2)^2-2*a(4))+6*a(2)*a(4)+6*a(1)*(-4*a(2)*a(3)+a(5))
Any ideas how?
The expected result after substitution should be
3*p_tensor(2,a(3))+6*tensor(p_tensor(2,a(1)),(5*p_tensor(2,a(2))-2*a(4))+6*tensor(a(2),a(4))+6*tensor(a(1),(-4*tensor(a(2),a(3))+a(5))
Regular expressions cannot do arbitrary nesting, nor can then do precedence and associativity. Parsers are required for that; however, you can get close enough by starting with this:
Perl:
while(<>) {
s/(a\(\d+\))\^(\d+)/p_tensor($2,$1)/g;
s/(a\((\d+)\))\*(a\((\d+)\))/tensor($1, $3)/g if $2 != $4;
print;
}
which is close, and gets you a single level. The extra nesting can then be "faked" by adding additional recursively defined patterns that go to whatever max nesting depth you need (often not many...expressions are rarely 3-4 levels deep in practice, which may be fine for you).
Try it with:
echo "3*a(3)^2+6*a(1)^2*(5*a(2)^2-2*a(4))+6*a(2)*a(4)+6*a(1)*(-4*a(2)*a(3)+a(5))" | perl t.pl
or something similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With