【问题标题】:Reading a large file in perl, record by record, with a dynamic record separator在 perl 中读取一个大文件,逐条记录,使用动态记录分隔符
【发布时间】:2011-01-13 17:09:26
【问题描述】:

我有一个脚本可以逐行读取一个大文件。我想使用的记录分隔符 ($/) 是 (\n)。唯一的问题是每一行的数据都包含CRLF字符(\r\n),程序不应该认为是行尾。

例如,这里是一个示例数据文件(写出换行符和 CRLF):

line1contents\n
line2contents\n
line3\r\ncontents\n
line4contents\n

如果我设置$/ = "\n",那么它将第三行分成两行。理想情况下,我可以将$/ 设置为匹配\n 而不是\r\n 的正则表达式,但我认为这是不可能的。另一种可能性是读取整个文件,然后使用 split 函数在所述正则表达式上进行拆分。唯一的问题是文件太大而无法加载到内存中。

有什么建议吗?

【问题讨论】:

    标签: perl performance file-io


    【解决方案1】:

    对于这个特定任务,检查行尾并根据需要附加下一行听起来很简单:

    $/ = "\n";
    ...
    while(<$input>) {
        while( substr($_,-2) eq "\r\n" ) {
            $_ .= <$input>;
        }
        ...
    }
    

    这与在许多不同的编程上下文中支持 line continuation 的逻辑相同。

    您是对的,您不能将$/ 设置为正则表达式。

    【讨论】:

    • +1:这是迄今为止唯一适用于给定数据的建议。使用 'dos2unix' 进行转换会完全破坏文件的结构,并且将 '\r\n' 转换为空格、制表符或其他内容可能很难反转 - 您必须选择不能出现在行正文中的替换.
    • 谢谢,这是一个非常简单的方法,我不敢相信我没有想到。这甚至可以应用于模式更复杂的更一般情况。
    【解决方案2】:

    dos2unix 会为“\r\n”添加一个 UNIX 换行符,因此并不能真正解决问题。我会使用一个正则表达式,用空格或制表符替换“\r\n”的所有实例,并将结果保存到不同的文件中(因为您不想在这些点拆分行)。然后我会在新文件上运行你的脚本。

    【讨论】:

      【解决方案3】:

      先尝试在文件上使用dos2unix,然后正常读入。

      【讨论】:

      • 从 OP 看来 \r\n 是一种 escape \n 而不是“坏” \n 的方法。
      猜你喜欢
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      • 2016-04-13
      • 2021-08-14
      • 1970-01-01
      相关资源
      最近更新 更多