Chinaunix

标题: 如何用AWK或sed或Perl替换这样的文本?高手测试 :) [打印本页]

作者: 预言家    时间: 2012-12-13 13:32
标题: 如何用AWK或sed或Perl替换这样的文本?高手测试 :)
本帖最后由 预言家 于 2012-12-13 14:26 编辑

想把乘法符号 "*" 替换成 "tensor", 指数符号 "^" 替换成 "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))


作者: yinyuemi    时间: 2012-12-14 01:53
这已经不是简单的替换吧,应该是写一个命令解释器
作者: 预言家    时间: 2012-12-14 04:41
yinyuemi 发表于 2012-12-14 01:53
这已经不是简单的替换吧,应该是写一个命令解释器


可以讲讲怎样写一个处理这个简单算法的命令解释器吗?

作者: mcshell    时间: 2012-12-14 08:54
yinyuemi 发表于 2012-12-14 01:53
这已经不是简单的替换吧,应该是写一个命令解释器

同意~~
我用平衡组只能取出所有符合要求的元素,替换的话 就麻烦了。。替换还要嵌套回去
作者: seesea2517    时间: 2012-12-14 10:12
括号和你的结果有此许不同,你检查检查,另外从简考虑,使用 /([a-z]+\([^()^]+\))\^([0-9])/ 的正则,所以暂不支持a(a(i))^2这样的嵌套格式,只支持 a(i)^2 的单层格式,如果有需要你再改进这个正则就行了:
  1. [seesea2517@UC ~]# awk -f a.awk a.txt
  2. 原始:5*a(i)*a(j)*(a(k1)+3*a(k2))
  3. 替换:5*tensor(tensor(a(i),a(j)),(a(k1)+3*a(k2)))
  4. -------------
  5. 原始:a(i)^2*a(j)^2
  6. 替换:tensor(p_tensor(2,a(i)),p_tensor(2,a(j)))
  7. -------------
  8. 原始: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))

  9. 替换:3*p_tensor(2,a(3))+6*tensor(p_tensor(2,a(1)),(5*p_tensor(2,a(2))-2*a(4)))+
  10. 6*tensor(a(2),a(4))+6*tensor(a(1),(-4*tensor(a(2),a(3))+a(5)))
  11. -------------
  12. 原始:5*a(2)^2-2*a(4)
  13. 替换:5*p_tensor(2,a(2))-2*a(4)
  14. -------------

  15. [seesea2517@UC ~]# cat a.txt
  16. 5*a(i)*a(j)*(a(k1)+3*a(k2))
  17. a(i)^2*a(j)^2
  18. 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))
  19. 5*a(2)^2-2*a(4)
  20. [seesea2517@UC ~]# cat a.awk
  21. function tensor(line, _ARGEND_, ar, len, i, str, flag, ar_tokens, count, result,
  22. temp)
  23. {
  24.     count = 0
  25.     str  = ""
  26.     flag = 0
  27.     i = 1
  28.     len  = split(line, ar, "")

  29.     if (ar[1] == "(")
  30.     {
  31.         if (ar[len] != ")")
  32.         {
  33.             print "括号不匹配。"
  34.             exit
  35.         }

  36.         ++i
  37.         --len
  38.     }

  39.     for (; i <= len; ++i)
  40.     {
  41.         if (ar[i] == "(")
  42.             flag++

  43.         if (ar[i] == ")")
  44.             flag--

  45.         if (flag < 0)
  46.         {
  47.             print "括号不匹配。"
  48.             exit
  49.         }

  50.         if (flag == 0 && (ar[i] ~ /[+*/]/ || (ar[i] == "-" && ar[i-1] ~ /[0-9)]/
  51. )))
  52.         {
  53.             ar_tokens[count++] = ar[i]
  54.             str = ""
  55.             continue
  56.         }

  57.         str = str""ar[i]
  58.         if (i == len || (ar[i+1] ~ /[-+*/]/ && flag == 0))
  59.         {
  60.             if (str ~ /^\(/)
  61.             {
  62.                 ar_tokens[count++] = "("tensor(str)")"
  63.             } else {
  64.                 ar_tokens[count++] = str
  65.             }
  66.         }
  67.     }

  68.     result = ""
  69.     temp = ""
  70.     for (i = 0; i < count; ++i)
  71.     {
  72.         if (temp == "")
  73.             temp = ar_tokens[i]

  74.         if (ar_tokens[i+1] == "*" && temp !~ /^[-0-9]+$|^$/)
  75.         {
  76.             temp = "tensor("temp","ar_tokens[i+2]")"
  77.             i += 2

  78.             if (i < count)
  79.             {
  80.                 i--
  81.                 continue
  82.             }
  83.         }

  84.         result = result""temp
  85.         temp = ""
  86.     }

  87.     return result
  88. }

  89. BEGIN {
  90.     FS=""
  91. }

  92. {
  93.     print "原始:" $0
  94.     print "替换:" gensub(/([a-z]+\([^()^]+\))\^([0-9])/, "p_tensor(\\2,\\1)", "g", tensor($0))
  95.     print "-------------"
  96. }
复制代码

作者: seesea2517    时间: 2012-12-14 10:14
屏幕宽度不够换行了,修正一下:
  1. [seesea2517@UC ~]# awk -f a.awk a.txt
  2. 原始:5*a(i)*a(j)*(a(k1)+3*a(k2))
  3. 替换:5*tensor(tensor(a(i),a(j)),(a(k1)+3*a(k2)))
  4. -------------
  5. 原始:a(i)^2*a(j)^2
  6. 替换:tensor(p_tensor(2,a(i)),p_tensor(2,a(j)))
  7. -------------
  8. 原始: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))

  9. 替换: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)))
  10. -------------
  11. 原始:5*a(2)^2-2*a(4)
  12. 替换:5*p_tensor(2,a(2))-2*a(4)
  13. -------------

  14. [seesea2517@UC ~]# cat a.txt
  15. 5*a(i)*a(j)*(a(k1)+3*a(k2))
  16. a(i)^2*a(j)^2
  17. 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))
  18. 5*a(2)^2-2*a(4)
  19. [seesea2517@UC ~]# cat a.awk
  20. function tensor(line, _ARGEND_, ar, len, i, str, flag, ar_tokens, count, result, temp)
  21. {
  22.     count = 0
  23.     str  = ""
  24.     flag = 0
  25.     i = 1
  26.     len  = split(line, ar, "")

  27.     if (ar[1] == "(")
  28.     {
  29.         if (ar[len] != ")")
  30.         {
  31.             print "括号不匹配。"
  32.             exit
  33.         }

  34.         ++i
  35.         --len
  36.     }

  37.     for (; i <= len; ++i)
  38.     {
  39.         if (ar[i] == "(")
  40.             flag++

  41.         if (ar[i] == ")")
  42.             flag--

  43.         if (flag < 0)
  44.         {
  45.             print "括号不匹配。"
  46.             exit
  47.         }

  48.         if (flag == 0 && (ar[i] ~ /[+*/]/ || (ar[i] == "-" && ar[i-1] ~ /[0-9)]/)))
  49.         {
  50.             ar_tokens[count++] = ar[i]
  51.             str = ""
  52.             continue
  53.         }

  54.         str = str""ar[i]
  55.         if (i == len || (ar[i+1] ~ /[-+*/]/ && flag == 0))
  56.         {
  57.             if (str ~ /^\(/)
  58.             {
  59.                 ar_tokens[count++] = "("tensor(str)")"
  60.             } else {
  61.                 ar_tokens[count++] = str
  62.             }
  63.         }
  64.     }

  65.     result = ""
  66.     temp = ""
  67.     for (i = 0; i < count; ++i)
  68.     {
  69.         if (temp == "")
  70.             temp = ar_tokens[i]

  71.         if (ar_tokens[i+1] == "*" && temp !~ /^[-0-9]+$|^$/)
  72.         {
  73.             temp = "tensor("temp","ar_tokens[i+2]")"
  74.             i += 2

  75.             if (i < count)
  76.             {
  77.                 i--
  78.                 continue
  79.             }
  80.         }

  81.         result = result""temp
  82.         temp = ""
  83.     }

  84.     return result
  85. }

  86. BEGIN {
  87.     FS=""
  88. }

  89. {
  90.     print "原始:" $0
  91.     print "替换:" gensub(/([a-z]+\([^()^]+\))\^([0-9])/, "p_tensor(\\2,\\1)", "g", tensor($0))
  92.     print "-------------"
  93. }
复制代码

作者: 预言家    时间: 2012-12-14 11:05
很好很强大 搬来板凳细看

seesea2517 发表于 2012-12-14 10:14
屏幕宽度不够换行了,修正一下:

作者: seesea2517    时间: 2012-12-14 11:09
回复 7# 预言家


    代码很丑,能不看尽量别看……
作者: 预言家    时间: 2012-12-14 11:56
本帖最后由 预言家 于 2012-12-14 11:57 编辑

完美!

在倒数第三行加上"+", 这样当指数为多位数字的时候,也可以匹配
print "替换:" gensub(/([a-z]+\([^()^]+\))\^([0-9]+)/, "p_tensor(\\2,\\1)", "g", tensor($0))


回复 6# seesea2517


   
作者: 预言家    时间: 2012-12-14 12:02
seesea2517 发表于 2012-12-14 11:09
回复 7# 预言家


哈 强大就好

以下是用perl写的,只能匹配最简单的情形,没有你的强大

  1. $cat tensor.pl

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

  1. 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 tensor.pl
复制代码
得到

  1.   3*p_tensor(2,a(3))+**6*p_tensor(2,a(1))*(5*p_tensor(2,a(2))**-2*a(4))+6*tensor(a(2), a(4))+6*a(1)*(-4*tensor(a(2), a(3))+a(5))
复制代码

作者: seesea2517    时间: 2012-12-14 13:09
回复 9# 预言家


    我没理解成指数固定为 2 就算不错了。
作者: seesea2517    时间: 2012-12-14 13:11
预言家 发表于 2012-12-14 12:02
哈 强大就好

以下是用perl写的,只能匹配最简单的情形,没有你的强大得到


厉害啊,简洁强大。

结果里的标红处是特意的么。
3*p_tensor(2,a(3))+**6*p_tensor(2,a(1))*(5*p_tensor(2,a(2))**-2*a(4))+6*tensor(a(2), a(4))+6*a(1)*(-4*tensor(a(2), a(3))+a(5))
作者: dolphinlater    时间: 2012-12-19 23:10
  1. s/\([a-z][a-z]*\)(\([0-9][0-9]*\))/\1#\2@/g
  2. s/\([a-z][a-z]*#[0-9][0-9]*@\)^\([0-9][0-9]*\)/p_tensor#\2,\1@/g
  3. s/\([\+-\*]\)\([a-z][a-z0-9_#@,]*\|([^()]*)\)\*\([a-z][a-z0-9_#@,]*\|([^()]*)\)/\1tensor#\2,\3@/g
  4. s/\([a-z][a-z0-9_#@,]*\)\*\([a-z][a-z0-9_#@,]*\)/tensor#\1,\2@/g
  5. s/#/(/g
  6. s/@/)/g
复制代码
sed版本,可惜只能处理一层嵌套,切不支持中间存在空格,请有心人继续完善吧。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2