一个隐蔽的BUG,搞了半天~

一个隐蔽的BUG,搞了半天~

在windows下新建文件a内容如下:
11111111
22222222
33333333
将文件传到linux系统中。

perl脚本b大体如下:
local $line;
while(<STDIN>){
    if( $_ =~ /(.+)/ ){
        $line .= $1;
    }
}

print $line;


执行命令:cat a | ./b
结果只显示:33333333,前两行都失踪了,非常郁闷。

经调试,将$line写入文件,才发现内容是正确的:
11111111^M22222222^M33333333

原来是\r在搞鬼。
Windows到Linux的ftp要选ascii。
dos2unix a
原来这样,谢楼上~
是啊。
chomp 也有同样问题,去不掉\r。如果向终端输出就有问题。

不是说perl跨平台吗,不知这个函数为什么是这种行为方式。
perl的chomp只会管换行字符 "\n"...

\r 是return字符...回到第一个位置...

你可以看perldoc -f chomp

chomp 可从来都没有说可以处理\r...

\r是windows自己加上去的..

perl最早是在unix上开发的....
windows 下会碰到问题..也是正常的..


QUOTE:
原帖由 apile 于 2008-1-28 12:32 发表
perl的chomp只会管换行字符 "\n"...

\r 是return字符...回到第一个位置...

你可以看perldoc -f chomp

chomp 可从来都没有说可以处理\r...

\r是windows自己加上去的..

perl最早是在unix上开发的. ...

你这个理解不对。
chomp 其实去掉的是 $/,因此楼主的问题和 $/ 的设置有关。


QUOTE:
原帖由 apile 于 2008-1-28 12:32 发表
perl的chomp只会管换行字符 "\n"...

\r 是return字符...回到第一个位置...

你可以看perldoc -f chomp

chomp 可从来都没有说可以处理\r...

\r是windows自己加上去的..

perl最早是在unix上开发的. ...

我的意思是perl为什么不考虑添加个chomp1类似的内置函数,用以处理跨平台的换行问题。这样代码看起来会更漂亮些,维护也方便。


QUOTE:
原帖由 flw 于 2008-1-28 13:06 发表

你这个理解不对。
chomp 其实去掉的是 $/,因此楼主的问题和 $/ 的设置有关。

I got it


QUOTE:
原帖由 Cocory 于 2008-1-28 13:12 发表

I got it

Perl 是强大的,你不应该轻易怀疑它。碰到问题的时候,记得阅读 perldoc。
说实话,你那个回复我早就看到了,
不过因为是文档中很容易便可以找得到的,
因此懒得回。
后来看到 apile 大侠的理解不正确,
这才出来纠正一下。

[Copy to clipboard] [ - ]
CODE:
D:\MoChou>perldoc -f chomp
    chomp VARIABLE
    chomp( LIST )
    chomp   This safer version of "chop" removes any trailing string that
            corresponds to the current value of $/ (also known as
            $INPUT_RECORD_SEPARATOR in the "English" module). It returns the
            total number of characters removed from all its arguments. It's
            often used to remove the newline from the end of an input record
            when you're worried that the final record may be missing its
            newline. When in paragraph mode ("$/ = """), it removes all
            trailing newlines from the string. When in slurp mode ("$/ =
            undef") or fixed-length record mode ($/ is a reference to an
            integer or the like, see perlvar) chomp() won't remove anything.
            If VARIABLE is omitted, it chomps $_. Example:

                while (<>) {
                    chomp;  # avoid \n on last field
                    @array = split(/:/);
                    # ...
                }

            If VARIABLE is a hash, it chomps the hash's values, but not its
            keys.

            You can actually chomp anything that's an lvalue, including an
            assignment:

                chomp($cwd = `pwd`);
                chomp($answer = <STDIN>);

            If you chomp a list, each element is chomped, and the total
            number of characters removed is returned.

            Note that parentheses are necessary when you're chomping
            anything that is not a simple variable. This is because "chomp
            $cwd = `pwd`;" is interpreted as "(chomp $cwd) = `pwd`;", rather
            than as "chomp( $cwd = `pwd` )" which you might expect.
            Similarly, "chomp $a, $b" is interpreted as "chomp($a), $b"
            rather than as "chomp($a, $b)".

用tr或者s去掉不就得了。