7

次の置換規則を使用して、乗算記号「*」を「tensor」に、累乗記号「^」を「p_tensor」に置換したい。

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

ただし、3 * a(i)のように、記号「*」が数値と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))
4

1 に答える 1

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;
}

これは近くにあり、単一のレベルになります。次に、必要な最大の入れ子の深さに行く再帰的に定義されたパターンを追加することで、余分な入れ子を「偽造」できます(多くの場合、式は実際には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

または同様のもの。

于 2012-12-13T04:57:46.173 に答える