Chinaunix

标题: 关于 =~ s/../../g 转换的问题 [打印本页]

作者: bestnet009    时间: 2009-07-28 00:37
标题: 关于 =~ s/../../g 转换的问题
#!/usr/bin/perl
$aa = "<a>asfsafasdfsa<c>";
$ab = "(<a>)(.*)(<c>)";
$aa =~ s/$ab/$3$2$1/g;
print "$aa\n";
输出结果为: <c>asfsafasdfsa<a>


为什么上面的程序程序改成下面的(红色部份), 就不能执行了?

#!/usr/bin/perl
$aa = "<a>asfsafasdfsa<c>";
$ab = "(<a>)(.*)(<c>)";
$cc = "$3$2$1";
$aa =~ s/$ab/$cc/g;
print "$aa\n";
作者: Perl_Er    时间: 2009-07-28 08:53
标题: 回复 #1 bestnet009 的帖子
$cc = "$3$2$1"; 这个会取$3,$2,$1的值,因为他们都是undef,$cc为空,所以你替换后是空的
试下下面的代码,打印一下$1$2$3.
  1. $aa = "<a>asfsafasdfsa<c>";
  2. $ab = "(<a>)(.*)(<c>)";
  3. $cc = "$3$2$1";
  4. [color=Red]print $1;
  5. print $2;
  6. print $3;[/color]
  7. $aa =~ s/$ab/$cc/g;
  8. print "$aa\n";
复制代码

[ 本帖最后由 Perl_Er 于 2009-7-28 09:02 编辑 ]
作者: blackold    时间: 2009-07-28 10:09
标题: 回复 #1 bestnet009 的帖子
在双引号中会产生interpolation
作者: maklive8    时间: 2009-07-28 11:39
标题: 回复 #1 bestnet009 的帖子
$cc = "$3$2$1"这句给$cc赋值了,后面即使$3$2$1变化,$cc也不跟着变了
作者: bestnet009    时间: 2009-07-28 21:03
标题: 回复 #2 Perl_Er 的帖子
加了
print $1;
print $2;
print $3;
还是不行
作者: Perl_Er    时间: 2009-07-28 21:09
标题: 回复 #5 bestnet009 的帖子
加这些是为了打印的值,debug.
作者: bestnet009    时间: 2009-07-28 21:19
标题: 回复 #6 Perl_Er 的帖子
程序还是执行不了, 显示的错误报告是:

Use of uninitialized value $3 in concatenation (.) or string at Untitled line 4.
Use of uninitialized value $2 in concatenation (.) or string at Untitled line 4.
Use of uninitialized value $1 in concatenation (.) or string at Untitled line 4.
作者: maklive8    时间: 2009-07-29 00:27
原帖由 bestnet009 于 2009-7-28 21:19 发表
程序还是执行不了, 显示的错误报告是:

Use of uninitialized value $3 in concatenation (.) or string at Untitled line 4.
Use of uninitialized value $2 in concatenation (.) or string at Untitled l ...


确实在$aa =~ s/$ab/$3$2$1/g;这句之前$1 $2 $3都是uninitialized呀,吧uninitialized的值赋给$cc才出错的
作者: MMMIX    时间: 2009-07-29 09:14
原帖由 bestnet009 于 2009-7-28 00:37 发表
为什么上面的程序程序改成下面的(红色部份), 就不能执行了?

#!/usr/bin/perl
$aa = "<a>asfsafasdfsa<c>";
$ab = "(<a>)(.*)(<c>)";
$cc = "$3$2$1";

把最后一行中的双引号换成单引号。
作者: linuxty    时间: 2009-07-29 09:22
原帖由 MMMIX 于 2009-7-29 09:14 发表

把最后一行中的双引号换成单引号。



还是不行的,这样直接就把$aa 赋值成字符串 $1$2$3 了
作者: MMMIX    时间: 2009-07-29 09:27
原帖由 linuxty 于 2009-7-29 09:22 发表



还是不行的,这样直接就把$aa 赋值成字符串 $1$2$3 了

oops,再把下一行的 /g 换成 /gee.

[ 本帖最后由 MMMIX 于 2009-7-29 09:34 编辑 ]
作者: linuxty    时间: 2009-07-29 09:41
原帖由 MMMIX 于 2009-7-29 09:27 发表

oops,再把下一行的 /g 换成 /ge.


老大  还是不得行  还有什么要注意的 ....
作者: MMMIX    时间: 2009-07-29 09:47
原帖由 linuxty 于 2009-7-29 09:41 发表


老大  还是不得行  还有什么要注意的 ....

OK, the final answer:


  1. $cc = '$3 . $2 . $1';
  2. $ss =~ s/$ab/$cc/ee;
复制代码

作者: linuxty    时间: 2009-07-29 09:49
喔  明白了 谢谢老大

[ 本帖最后由 linuxty 于 2009-7-29 09:53 编辑 ]
作者: MMMIX    时间: 2009-07-29 09:51
原帖由 linuxty 于 2009-7-29 09:41 发表


老大  还是不得行  还有什么要注意的 ....

This works too:


  1. $cc = '"$3$2$1"';
  2. $ss =~ s/$ab/$cc/ee;
复制代码

作者: MMMIX    时间: 2009-07-29 09:52
原帖由 linuxty 于 2009-7-29 09:49 发表
replacement的分隔符是单引号时,作为单引号字符串,不会进行变量赋值.
/e修饰符是不是也要要求replacement不是单引号字符串 ?

嘛意思?
作者: linuxty    时间: 2009-07-29 09:54
原帖由 MMMIX 于 2009-7-29 09:52 发表

嘛意思?


想错了 发了帖才看到你发的帖  恍然大悟   嘻嘻
作者: linuxty    时间: 2009-07-29 10:05
/ee 是对求值的结果再求值,在这就是对 $c 替换成 $1$2$3 后再替换成匹配的值.

$c='$1$2$3'  $c='$1.$2.$3'  $c='"$1$2$3"' 3种方式.

为什么第1种不能替换,而2和3种可以替换也?
作者: Perl_Er    时间: 2009-07-29 10:26
标题: 回复 #18 linuxty 的帖子
/e是把//内的当作一段代码执行,第一个里面没有操作符,想一下假设$a$b$c放在一起执行会不会有问题,中间没有操作符连接,
第二个就不用说了,用.操作符连接了。第三个的话吧$1$2$3一起当作了一个字符串。
作者: MMMIX    时间: 2009-07-29 10:28
原帖由 linuxty 于 2009-7-29 10:05 发表
/ee 是对求值的结果再求值,在这就是对 $c 替换成 $1$2$3 后再替换成匹配的值.

$c='$1$2$3'  $c='$1.$2.$3'  $c='"$1$2$3"' 3种方式.

为什么第1种不能替换,而2和3种可以替换也?

其实这个错误信息已经说得很明白了。

最后执行的实际是 eval $1$2$3, 那么这里的 $1$2$3 是什么意思呢?它不在字符串中,所以不存在插值,因此 perl 将它理解为一个 expression,那么就需要 operator,找不到,所以报错。针对这个错误的修改就是后两种情况了,要么增加 operator .,使得 $1 . $2 . $3 成为一个合法的 expression, 或者把 $1$2$3 放在字符串中进行插值。
作者: MMMIX    时间: 2009-07-29 10:30
原帖由 linuxty 于 2009-7-29 10:05 发表
/ee 是对求值的结果再求值,在这就是对 $c 替换成 $1$2$3 后再替换成匹配的值.

$c='$1$2$3'  $c='$1.$2.$3'  $c='"$1$2$3"' 3种方式.

为什么第1种不能替换,而2和3种可以替换也?

BTW, 其实第二种和第三种方式是一样的,插值最后也会调用 . 连接字符串。
作者: linuxty    时间: 2009-07-29 10:48
谢谢 MMMIX Perl_Er
作者: linuxty    时间: 2009-07-29 11:20
原帖由 MMMIX 于 2009-7-29 10:28 发表

其实这个错误信息已经说得很明白了。

最后执行的实际是 eval $1$2$3, 那么这里的 $1$2$3 是什么意思呢?它不在字符串中,所以不存在插值,因此 perl 将它理解为一个 expression,那么就需要 operator,找不 ...



第一个/e时是执行 eval $c  这里的 $c 可以理解为expression ? 也没有operator啊?
作者: MMMIX    时间: 2009-07-29 11:27
原帖由 linuxty 于 2009-7-29 11:20 发表



第一个/e时是执行 eval $c  这里的 $c 可以理解为expression ? 也没有operator啊?

不是这样的。

第一个 /e 相当于 eval { $f },得到的是 $f 的值,第二个 /e 就是对 $f 的值进行 eval。
作者: MMMIX    时间: 2009-07-29 11:28
原帖由 linuxty 于 2009-7-29 11:20 发表



第一个/e时是执行 eval $c  这里的 $c 可以理解为expression ? 也没有operator啊?

这里有个类似的帖子,可以看下:
http://bbs3.chinaunix.net/viewthread.php?tid=1507269
作者: maklive8    时间: 2009-07-29 12:55
原帖由 MMMIX 于 2009-7-29 11:27 发表

不是这样的。

第一个 /e 相当于 eval { $f },得到的是 $f 的值,第二个 /e 就是对 $f 的值进行 eval。


有道理!!好强啊。

可不可以这样理解?

eval {$1$2$3} 和eval '$1$2$3' 一样,结果都是一个字符串$1$2$3。第二个/e才会看$1, $2和$3分别是什么,而给字符串$1$2$3加上""才能做插值。
作者: linuxty    时间: 2009-07-29 13:33
原帖由 MMMIX 于 2009-7-29 11:28 发表

这里有个类似的帖子,可以看下:
http://bbs3.chinaunix.net/viewthread.php?tid=1507269


一直以为 eval 只能用于 捕获错误,想不到还有另一个功能.

太强大了  谢谢老大了
作者: MMMIX    时间: 2009-07-29 14:10
原帖由 maklive8 于 2009-7-29 12:55 发表

可不可以这样理解?

eval {$1$2$3} 和eval '$1$2$3' 一样,结果都是一个字符串$1$2$3。

eval { $1$2$3 } 固然和 eval '$1$2$3'  一样,但它们的结果不是字符串 $1$2$3, 而是把 $1$2$3 作为 expression 求值(eval)后的结果。事实上,这是第二个 /e 执行的东西。
作者: maklive8    时间: 2009-07-29 15:30
原帖由 MMMIX 于 2009-7-29 14:10 发表

eval { $1$2$3 } 固然和 eval '$1$2$3'  一样,但它们的结果不是字符串 $1$2$3, 而是把 $1$2$3 作为 expression 求值(eval)后的结果。事实上,这是第二个 /e 执行的东西。


。。。又糊涂了,结果不是字符串 $1$2$3?把 $1$2$3 作为 expression 求值(eval)后的结果不还是$1$2$3吗?

就像 $c='$1', $c的值不就是 一个 $ 和一个 1组成的字符串吗?
作者: Perl_Er    时间: 2009-07-29 15:51
就像 $c='$1', $c的值不就是 一个 $ 和一个 1组成的字符串吗?

这是第一次,还有第二次了。
先休息一下吧。晕了想不清楚的
作者: MMMIX    时间: 2009-07-29 16:26
原帖由 maklive8 于 2009-7-29 15:30 发表


把 $1$2$3 作为 expression 求值(eval)后的结果不还是$1$2$3吗?

怎么会?这是个非法的表达式(连续的三个 variable, 没有 operator)

就像 $c='$1', $c的值不就是 一个 $ 和一个 1组成的字符串吗?

没错,$c 作为一个表达式,它的值是字符串 $1,那么 $c$c 作为一个表达式,它的值是什么?或者,它合法么?
作者: redicaps    时间: 2009-07-29 16:36
eval {$1$2$3} = eval '$1$2$3'是一样的,但这种写法有语法错误

/e相当于 eval 'EXP',相当于eval {EXP}
/ee 相当于 eval "EXP",相当于 eval EXP,会对EXP先进行插值处理

eg:
$c = 'balla';
$a = '$c';

eval {$a}返回的是$a的内容 $c
eval "$a"先对$a插值,得到$a,然后对$c eval获得'balla';
作者: Perl_Er    时间: 2009-07-29 17:05
With an eval, you should be especially careful to remember what's being looked at when:

   1. eval $x; # CASE 1
   2. eval "$x"; # CASE 2
   3.
   4. eval '$x'; # CASE 3
   5. eval { $x }; # CASE 4
   6.
   7. eval "\$$x++"; # CASE 5
   8. $$x++; # CASE 6

Cases 1 and 2 above behave identically: they run the code contained in the variable $x. (Although case 2 has misleading double quotes making the reader wonder what else might be happening (nothing is).) Cases 3 and 4 likewise behave in the same way: they run the code '$x' , which does nothing but return the value of $x. (Case 4 is preferred for purely visual reasons, but it also has the advantage of compiling at compile-time instead of at run-time.) Case 5 is a place where normally you would like to use double quotes, except that in this particular situation, you can just use symbolic references instead, as in case 6.
作者: bestnet009    时间: 2009-07-30 00:31
多谢楼上各位的答复, 困扰了2天的问题终于解决了

#!/usr/bin/perl
$aa = "<a>asfsafasdfsa<c>";
$ab = "(<a>)([^<]+)(<c>)";
$cc = '$3.$2.$1';
$aa =~ s/$ab/$cc/gee;
print "$aa\n";
作者: maklive8    时间: 2009-07-30 10:59
强人还真是多,我也要谢谢各位,我之前的理解确实有不少问题
作者: beyondfly    时间: 2009-07-30 14:17
原帖由 linuxty 于 2009-7-29 09:41 发表


老大  还是不得行  还有什么要注意的 ....



四川or重庆人氏
作者: linuxty    时间: 2009-07-30 15:00
原帖由 beyondfly 于 2009-7-30 14:17 发表



四川or重庆人氏


哇晒 好猛 一猜就中了




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