【问题标题】:How to do such substitutions with AWK or sed or Perl?如何使用 AWK 或 sed 或 Perl 进行此类替换?
【发布时间】:2012-11-30 22:41:45
【问题描述】:

想用“张量”替换乘法符号“*”,用“p_tensor”替换幂符号“^”:

    a(k)^n --> p_tensor(n,a(k))
    a(i)*a(j) --> tensor(a(i),a(j)), when i=/=j

但是当符号“*”在数字和a(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)))
    ...

现在我想使用 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))

有什么想法吗?

替换后的预期结果应该是

    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))

【问题讨论】:

  • 为什么你用tensor替换一些*,而不是其他的?即,第一个3*a(3)^2 似乎应该是tensor(3,p_tensor(2,a(3))
  • 是的,我应该提一下,“张量”仅用于替换符号“*”,这是两个a(i)之间的二元运算符。
  • 我想不出一种简单的方法来做到这一点,尤其是在这种特殊情况下......至少不是以任何干净的方式。您可能希望将原始表达式解析为表达式树,然后在必要时将其转换为使用您的操作。
  • 由于涉及括号,您很可能必须设置某种解析器来标记输入并单独处理每个标记。
  • @JackManey 知道如何设置某种解析器来标记输入并单独处理每个标记吗?

标签: perl bash shell sed awk


【解决方案1】:

正则表达式不能做任意嵌套,也不能做优先级和关联性。为此需要解析器;但是,您可以从以下开始就足够接近:

Perl:

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

这很接近,并且可以为您提供一个级别。然后可以通过添加额外的递归定义的模式来“伪造”额外的嵌套,这些模式可以达到您需要的任何最大嵌套深度(通常不是很多......实际上表达式很少有 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

或类似的东西。

【讨论】:

  • 您能否说明将“6*a(1)^2*(5*a(2)^2-2*a(4))”完整翻译为“ 6*tensor(p_tensor(2,a(1)),(5*p_tensor(2,a(2))-2*a(4))"。用当前脚本,翻译成"6*p_tensor(2 ,a(1))*(5*p_tensor(2,a(2))-2*a(4))".
  • 我不确定您遵循什么规则...您为产品提供的规则涉及 a(i) 形式的内容。如果您说您需要获取各种任意产品并将它们转换为张量调用,那么您将需要一个解析器,不幸的是。你可以在 perl 中写这样的东西,但它会很丑(你必须预先计算括号等)。有很多很好的工具可以做到这一点。参见 GNU bison 或 ANTLR。
猜你喜欢
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2012-07-17
  • 2017-11-11
  • 2017-06-16
  • 2014-01-24
  • 1970-01-01
相关资源
最近更新 更多