使用perl解析csv文件类型中的字符串

时间:2011-10-11 20:03:51

标签: perl

我使用perl的Tie::File来解析.csv文件并匹配特定的字符串,它实际上是文件的第一个字符串/标题。

我遇到的问题可能是我的输入文件类型。导出数据文件的工具可以导出.csv或我试过并测试过的文本。

不知怎的,我仍然没有得到比赛。我的问题可能是双重的:  (1)我的正则表达式错误和/或(2)文件类型。

示例文件头/字符串(如果我cat文件):

??Global  Mail_Date.Dat

示例文件头/字符串(如果我在编辑器中打开,Apple的TextEdit.app)

Global  Mail_Date.Dat

这是八进制转储:

0000000 377 376   G  \0   l  \0   o  \0   b  \0   a  \0   l  \0      \0
        feff 0047 006c 006f 0062 0061 006c 0020
0000020      \0   M  \0   a  \0   i  \0   l  \0   _  \0   D  \0   a  \0
        0020 004d 0061 0069 006c 005f 0044 0061
0000040   t  \0   e  \0   .  \0   D  \0   a  \0   t  \0  \r  \0  \n  \0
        0074 0065 002e 0044 0061 0074 000d 000a

显然,执行操作系统cat会在字符串上显示前导??

代码:

use strict;
use warnings;
use Tie::File;
use File::Copy;

    for (@ARGV) {
        tie my @lines, "Tie::File", $_;             
        #shift @lines if $lines[0] =~ /^Global/;
        if ($lines[0] =~ /^Global/) 
        {
             print "We have a match, remove the line ..";
             #shift @lines if $lines[0] =~ /^Global/;
             untie @lines; 
        }
        else
        { 
             print "No match found. Exit";
        }

}

2 个答案:

答案 0 :(得分:1)

看起来你的文件是用utf16编码的。

尝试这样的事情:

binmode STDIN, ':encoding(UTF-16LE)';
while (<STDIN>) {
  if (m/Global/) {  # see note
    print "Matched Global on line $.\n";
  }
}

如果你得到一个匹配,那么至少我们知道编码是正确的。

为了补偿BOM代码点,您可以在binmode调用后读取一个字符:

binmode STDIN, ':encodeing(UTF-16LE)';
read(STDIN, my $buf, 1);
while (<STDIN>) {
  if (m/^Global/) { ... }
}

答案 1 :(得分:1)

我正在查看八进制转储并注意每个常规字符之间的空字符。也就是说,它是G-\0-l-\0-o-\0-b-\0-a-\0-l-\0而不是G-l-o-b-a-l。这意味着您的文件不是ASCII文本。这是UTF8还是UTF16?如果是这样,则在Perl中打开文件时必须使用encoding函数:

open(my $fh, "<:encoding(UTF-16)", $fileName)
    or die qq(Can't open file "$fileName" for reading);

如果这是csv文件,您应该尝试Text::CSV::Encoded模块。这有助于您解析CSV文件。