【问题标题】:Opening a CSV file created in Mac Excel with Perl使用 Perl 打开在 Mac Excel 中创建的 CSV 文件
【发布时间】:2011-06-26 22:05:18
【问题描述】:

我在使用下面的 Perl 代码时遇到了一些问题。我可以打开并读取手动创建的 CSV 文件,但如果我尝试打开保存为 CSV 文件的任何 Mac Excel 电子表格,下面的代码会将其全部读取为一行。

#!/usr/bin/perl

use strict;
use warnings;

open F, "file.csv";

foreach (<F>)
{
    ($first, $second, undef, undef) = split (',', $_);
}

print "$first : $second\n";

close(F);

【问题讨论】:

  • 您是在 OS X 还是 Windows 上运行 Perl?如果是 Windows,文件如何从 OS X 移动?

标签: perl excel macos csv


【解决方案1】:

始终为此目的使用专门的模块(例如Text::CSVText::CSV_XS),因为在很多情况下split-ing 无济于事(例如,当字段包含不是字段分隔符,但在引号内)。

【讨论】:

    【解决方案2】:

    传统的 Macintosh(系统 9 和更早版本)使用 CR (0x0D, \r) 作为行分隔符。 Mac OS X(基于 Unix)使用 LF(0x0A, \n) 作为默认行分隔符,因此作为 Unix 工具的 perl 脚本可能期待 LF,但得到 CR。由于文件中没有行分隔符,perl 认为只有一行。如果它有 Windows 行尾 (CR,LF),您可能会在每行的末尾得到一个不可见的 CR。

    将 0x0D 替换为 0x0A 的输入快速循环应该可以解决您的问题。

    【讨论】:

      【解决方案3】:

      我在 Excel 2004 for Mac 中直接遇到过这个问题。行尾确实是 \r,而 IIRC,文本使用 MacRoman 字符集,而不是您可能期望的 Latin-1 或 UTF-8。

      除了使用 Text::CSV / Text::CSV_XS 并在 \r 上拆分的好建议外,您还需要像这样使用 MacRoman 编码打开文件:

      open my $fh, "<:encoding(MacRoman)", $filename
         or die "Can't read $filename: $!";
      

      同样,在 Windows 上读取使用 Excel 导出的文件时,您可能希望在该代码中使用 :encoding(cp1252) 而不是 :encoding(MacRoman)

      【讨论】:

        【解决方案4】:

        不确定 Mac excel,但 Windows 版本肯定会将所有值括在引号中:"like","this"。此外,您需要考虑值中存在引号的可能性,这将显示为 "like""this"(该值中只有一个 ")。

        然而,要真正回答您的问题,它可能使用了与您预期不同的换行符。它可能保存为\r\n 而不是\n,反之亦然。

        【讨论】:

          【解决方案5】:

          正如其他人所怀疑的那样,您的行尾可能是罪魁祸首。在我的基于 Linux 的系统上,有内置实用程序可以更改这些行尾。 mac2unix(我认为这只是 dos2unix 的一个包装器,它将读取您的文件并为您更改行尾。您应该在 Linux 和 Mac 上都有类似的东西(微软可能不关心您)。

          如果您想在 Perl 中处理此问题,请查看设置 $/ 变量以将“输入记录分隔符”从“\n”设置为“\r”(如果这是正确的结尾)。在阅读文件之前尝试local $/ = "\r"。在perldoc perlvar(靠近$/)或perldoc perlport(致力于编写可移植的 Perl 代码)阅读更多相关信息。

          附:如果我有一些不正确的部分,请告诉我,我不使用 Mac,我只是想我知道这个理论

          【讨论】:

            【解决方案6】:

            如果您将处理它认为换行符的“特殊变量”设置为 \r,您将能够一次读取一行:$/="\r";在这种特殊情况下,perl 的 mac 新行是默认的 \n,但文件可能正在使用 \r。这建立在 Flynn1179 和 Mark Thalman 所说的基础之上,但向您展示了如何使用 while () 样式阅读。

            【讨论】:

              猜你喜欢
              • 2012-09-03
              • 2012-10-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-01-28
              相关资源
              最近更新 更多