2012-12-13 69 views
7

想替換乘法符號「*」和「張量」,和電源符號「^」與「p_tensor」使用下面的替換規則:如何用AWK或sed或Perl做這樣的替換?

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

爲什麼用'tensor'替換一些'*',而不是其他?也就是說,第一個'3 * a(3)^ 2'似乎應該是'tensor(3,p_tensor(2,a(3))'。 – ceyko

+0

是的,我應該提到這一點,「張量」只用於用兩個a(i)之間的二元運算符替換符號「*」 –

+0

我想不出一種簡單的方法來做到這一點,特別是在這種特殊情況下......至少不是以任何干淨的方式。以查看將原始表達式解析爲表達式樹,然後將其轉換爲在必要時使用您的操作。 – ceyko

回答

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 

或類似的東西:

與嘗試。

+0

很酷,謝謝Tony。 –

+0

@OsirisXu如何處理「accept」?:) –

+0

你可以對於「6 * a(1)^ 2 *(5 * a(2)^ 2-2 * a(4))」的完整譯文給出了「6 *張量(p_tensor(2,a 1)),(5 * p_tensor(2,(2)) - 2 * A(4))」。使用當前腳本,它被翻譯成「6 * p_tensor(2,a(1))*(5 * p_tensor(2,a(2)) - 2 * a(4))」。 –