如何使用AWK或sed或Perl进行此类替换?

Osi*_* Xu 7 bash shell perl awk sed

想要使用以下替换规则将乘法符号"*"替换为"tensor",将幂符号"^"替换为"p_tensor":

    a(k)^n --> p_tensor(n,a(k))
    a(i)*a(j) --> tensor(a(i),a(j)), when i=/=j
Run Code Online (Sandbox Code Playgroud)

但是当符号"*"在数字和(i)之间时,例如3*a(i),我们应该将符号"*"保持为它.

例如,

    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)))
    ...
Run Code Online (Sandbox Code Playgroud)

现在我想使用AWK或sed或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))
Run Code Online (Sandbox Code Playgroud)

有什么想法?

替换后的预期结果应为

    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))
Run Code Online (Sandbox Code Playgroud)

Ton*_* K. 7

正则表达式不能执行任意嵌套,也不能执行优先级和关联性.解析器是必需的; 但是,你可以从这开始:

Perl的:

while(<>) {
   s/(a\(\d+\))\^(\d+)/p_tensor($2,$1)/g;
   s/(a\((\d+)\))\*(a\((\d+)\))/tensor($1, $3)/g if $2 != $4;
   print;
}
Run Code Online (Sandbox Code Playgroud)

这很接近,让你达到一个单一的水平.额外的嵌套然后可以"伪造"通过添加额外的递归定义模式,去任何你需要的最大嵌套深度(通常不是很多......表情很少3-4水平在实践中深刻的,这可能是对你罚款).

尝试使用:

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
Run Code Online (Sandbox Code Playgroud)

或类似的东西.