免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yuanquan08
打印 上一主题 下一主题

各位大虾,小弟有难啊! [复制链接]

论坛徽章:
0
11 [报告]
发表于 2013-12-23 09:57 |只看该作者
回复 8# rubyish



谢谢,真的是我想要的结果。十分感谢!!!
小弟,虽然也试着用动态正则表达式进行分析,但是就是达不到效果。
感谢楼上各位的支持和帮忙!!!
今后,还望多多指教啊。。。
   

论坛徽章:
0
12 [报告]
发表于 2013-12-23 12:07 |只看该作者
再次请教,t  = (A interact  ((B  or  C)  or (((D inside E) or F)   not   inside G)))
表达式里面如果出现not的就将后面的变量删除,又该如何操作啊?
正如上面表达式希望出现如下内容:
t0 =  A_B
t1 =  A_C
t2 =  A_D_E
t3 =  A_F


论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
13 [报告]
发表于 2013-12-23 14:16 |只看该作者
回复 12# yuanquan08

remove it first
   

论坛徽章:
0
14 [报告]
发表于 2013-12-23 16:34 |只看该作者
回复 13# jason680
这个方法是简单,可是太多了。如果只有几个或者几十个地方出现可以手动先处理掉,但是有几百个地方啊。。。


   

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
15 [报告]
发表于 2013-12-23 16:46 |只看该作者
回复 14# yuanquan08


     not   inside G
  s/not\s+inside\s+\w+//g;

论坛徽章:
0
16 [报告]
发表于 2013-12-23 17:37 |只看该作者
谢谢楼上的回复。
我知道怎么替换,刚才只是不确定删掉哪些内容,不确定删掉之后还能不能正确匹配。。
我刚才试过了,还能得到我想要的结果。。。。

论坛徽章:
0
17 [报告]
发表于 2013-12-23 20:39 |只看该作者
本帖最后由 felonwan 于 2013-12-23 23:37 编辑
yuanquan08 发表于 2013-12-23 17:37
谢谢楼上的回复。
我知道怎么替换,刚才只是不确定删掉哪些内容,不确定删掉之后还能不能正确匹配。。
我 ...


呵呵,下面这样的么?
(( A not inside B) interact C )
这种情况好像比较麻烦啊,必须要考虑括号的配对。。。

你没明确说明可能遇到的情况,所以可能有误会。

另外,not后能不能跟interact和or?  A not interact B
not后能不能直接跟括号?    A not ( inside (B or C) )

论坛徽章:
7
巳蛇
日期:2014-04-10 08:54:57白羊座
日期:2014-04-22 20:06:262015年亚洲杯之沙特阿拉伯
日期:2015-02-10 14:18:532015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之吉达阿赫利
日期:2015-06-02 11:34:112015亚冠之武里南联
日期:2015-06-24 12:13:082015亚冠之阿尔纳斯尔
日期:2015-08-03 09:08:25
18 [报告]
发表于 2013-12-23 23:52 |只看该作者
本帖最后由 Monox 于 2013-12-23 23:55 编辑

这个用编译原理的知识实现应该会更方便,扩展和调试起来也应该更容易吧。先进行词法分析,把输入分解成一串标识符如 A, B, C and so on,三种二元操作符 interact, inside, or以及一种一元操作符 not,再就是左右括号的一个token流,然后对token流进行语法分析,构建语法树,最后将语法树进行解析就可以得到结果。
我并不打算提供代码(我真要按这种方式写代码的话也肯定不用Perl写,要么用C(用C的话多半我也不打算手写DFA,肯定会用Flex和YACC),要么用Haskell,如果有人对使用C或者Haskell实现这个感兴趣的话,在我闲得无聊的时候又没其他人提供这种方案的代码的话,我到是可以考虑试着写写),也怀疑楼主是否有能力用这种方案来做,不过我很好奇会不会有人采用我说的方案提供一份代码呢?

论坛徽章:
0
19 [报告]
发表于 2013-12-24 01:55 |只看该作者
本帖最后由 felonwan 于 2013-12-25 15:14 编辑

下面是我的包含了去not的版本(按我理解的not)。
刚学perl,现学现卖,只用了动态正则表达式(括号配对检查)、数组、判断和循环,连子函数都没用到哦。
不过各个部分有简单注释,大概能帮楼主明白思路。
经我测试有点小毛病,但是似乎不影响使用,楼主做点简单的小改动就能好,楼主就当家庭作业吧。

(12-25)版本,感觉基本完美了:
算法就是循环地这样做:删除不必要的成对括号,匹配第一个“(...a+b...)*C”或“A*(...b+c...)”这样的模式,然后展开。
“(...a+b...)*C”和“A*(...b+c...)”中的括号里面再不含括号,是可以使用分配律的基本单元,而A和C则可以是单个变量或一对括号包括的一个块。
A和C的匹配用到了递归正则表达式。
才发现楼主的东西比我想的加法和乘法运算还要简单,每两个变量运算后都加了括号,不会出现像(A or B or C)、(A inside B or C)等这样的类似情况。。。我想多了。。。

  1. #!/usr/bin/perl
  2. my $unit   = qr/ (?> [^()]+ | \( [^\(\)]*(??{ $unit}) [^\(\)]* \)  )* /x;
  3. while(<STDIN>){
  4.   chomp;
  5.   $_ =~ s/^.*=(.*)/$1/;

  6.   #inside/interact ==> *, or ==> +,delete space (转换为乘法、加法,删除空格)
  7.   $_ =~ s/inside|interact/*/g;
  8.   $_ =~ s/or/+/g;
  9.   $_ =~ s/ //g;
  10. #  print "$_\t\t(Original)\n";

  11.   # delete not  (去掉not)
  12.   (/not/) while
  13.     s/not(\+|\w|\*|\($unit\))+(\)|$)/$2/;
  14. #  print "==> $_\t\t(After deleted 'not')\n";

  15.   # Expansion (多项式展开)
  16.   # A*(...+b+c+...) ==> A*... +A*b +A*c +A*...
  17.   # (...+a+b+...)*C ==> ...*C +a*C +b*C +...*C
  18.   my $tmp;
  19.   my $line= $_;
  20.   my $line0;
  21.   my $count=1;
  22.   while("$line" ne "$line0"){
  23. #    print "\nCycle $count running...\n";
  24.     $line0 = $line;
  25.     $_ = $line;
  26.      # delete unnecessary '()'(删除不必要的成对括号)
  27.     (/\($unit\)/) while
  28.       s/(^|\()(\($unit\))(\)|$)/$2/; # ((...))==>(...)
  29.     (/\*/) while
  30.       s/\(([^\+]*\w+|\($unit\))*\*(\($unit\)|\w+[^\+]*)*\)/$1*$2/; # ...(a*b)... ==> a*b
  31.     (/\+/) while
  32.       s/(^|\+|\()\(([^\(\)]+|\($unit\))\+(\($unit\)|[^\(|\)]+)\)(\)|\+|$)/$1$2+$3$4/; # ^+((a+b)+)|$|)==>a+b+c`
  33.     $_ =~ s/^\(($unit)\)$/$1/;
  34. #    print "==> $_\t\t(deleted unnecessary '()')\n";
  35.     $line = $_;

  36.     foreach $i (qw/ab_C A_bc/){
  37.      if("$i" eq "ab_C"){
  38.         ($tmp = $line )=~ s/^(.*[\(|\*|\+]*)\(([^\(\)]*\w\+\w[^\(\)]*)\)\*(\($unit\)|\w+)(.*)/$1:$2:$3:$4/;# devide $line into 4 parts according to (...+a+b+...)*C matching(根据匹配的第一个(a+b)*C形式后拆分$line为四部分)
  39.       }
  40.       elsif("$i" eq "A_bc"){
  41.         ($tmp = $line )=~ s/(.*)(\($unit\)|\w+)\*\(([^\(\)]*\w+\+\w+[^\(\)]*)\)([\*|\+|\)]*.*)$/$1:$2:$3:$4/;# devide $line into 4 parts according to A*(...+B+C+...) matching (根据匹配的第一个A*(b+c)形式拆分$line为四部分)
  42.       }
  43. #      print "$i ==> $tmp\n";
  44.       @block =split(/:/,$tmp);
  45. #      print "Block head and tail: $block[0]\t$block[$#block]\n";
  46.       if($#block > 0){
  47.         $line = "$block[0]";
  48.         if(("$block[0]" ne '') | ("$block[3]" ne '')) {$line.="("};
  49.         if("$i" eq "ab_C"){
  50.           @fields = split(/\+/,$block[1]);
  51.           foreach $j (@fields) { $line.="$j*$block[2]+";} # join "a*C+","a*C+" (连接"a*C+","a*C+")
  52.         }
  53.         elsif("$i" eq "A_bc"){
  54.           @fields = split(/\+/,$block[2]);
  55.           foreach $j (@fields) { $line.="$block[1]*$j+";} # join "A*b+","A*c+" (连接"A*b+","A*c+")
  56.         }
  57.         $line =~ s/\+$//;
  58.         if(("$block[0]" ne '') | ("$block[3]" ne '')){$line.=")$block[3]";}
  59. #      print "==> $line\n";
  60.       }
  61.     }
  62. #    print "Cycle $count complete!\n";
  63.     if(($count++) >= 100){last;} #avoid infinite loop(防死循环)
  64.   }
  65. #print "\nFinal: $line\n\n";
  66. # print to desired format (打印成想要的格式)
  67. @parts=split(/\+/,$line);
  68. $count=0;
  69. foreach $part (@parts){
  70.   $part =~ s/\*/_/g;
  71.   printf "t".$count++." = $part\n";
  72. }
  73. print "\n";
  74. }
复制代码
楼主的两个例子放在logic文件中:

  1. $ cat logic | ./tl
  2. t0 = A_B
  3. t1 = A_C
  4. t2 = A_D_E_G
  5. t3 = A_F_G

  6. t0 = A_B
  7. t1 = A_C
  8. t2 = A_D_E
  9. t3 = A_F
复制代码
另外的例子:
  1. $ echo "(a+b*(c+d*(e+(f+g*(i+jnot*(k+(m+n)*l)))*h+o*(p+q+(r+s+t)*u))))" | ./tl
  2. t0 = a
  3. t1 = b_c
  4. t2 = b_d_e
  5. t3 = b_d_f_h
  6. t4 = b_d_g_i_h
  7. t5 = b_d_g_j_h
  8. t6 = b_d_o_p
  9. t7 = b_d_o_q
  10. t8 = b_d_o_r_u
  11. t9 = b_d_o_s_u
  12. t10 = b_d_o_t_u
复制代码

论坛徽章:
7
戌狗
日期:2013-12-15 20:43:38技术图书徽章
日期:2014-03-05 01:33:12技术图书徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16赛季CBA联赛之青岛
日期:2016-03-17 20:36:13
20 [报告]
发表于 2013-12-24 02:56 |只看该作者

for not
biru:
  1. #!/usr/bin/perl

  2. sub X {
  3.     map join( '_', split /\|/ ),
  4.       glob '{' . join( '}{', map join( '|,', @$_ ) . '|', @_ ) . '}';
  5. }

  6. sub From {
  7.     map { s/(\w+)/'$1',/g; s/\(/[/g; s/\)/],/g; eval } shift;
  8. }

  9. sub Extract {
  10.     my ( $Op, @data ) = @{ +shift }[ 1, 0, 2 ];
  11.       $Op eq 'not' ? map { ref $_ ? Extract($_) : $_ } $data[0]
  12.     : $Op eq 'or'  ? map { ref $_ ? Extract($_) : $_ } @data
  13.     : X map { ref $_ ? [ Extract($_) ] : [$_] } @data;
  14. }

  15. my $String = <DATA>;
  16. my @Result = Extract From $String;
  17. print $_ . $/ for @Result;

  18. __DATA__
  19. (A interact  ((B  or  C)  or (((D inside E) or F)   not   inside G)))
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP