You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl中替换与split处理CRLF换行符的问题排查与修复

Perl处理带CRLF换行符的CSV转换问题

问题背景

需要处理一批带有CRLF换行符的文本文件,完成以下转换:

  • 移除每行最后一个$符号
  • 将所有$替换为逗号,
  • 为每个字段添加双引号
  • 重命名输出为CSV文件

原始文件示例

$ cat -v file1.txt
1$XXX$ZZZ$$$$$$$$^M
2$AAA$BBB$$$$$$$$^M

$ cat -v file2.txt
1$4668$$$^M
2$46$$$^M

期望输出

$ cat newname1.csv
"1","XXX","ZZZ","","","","","","",""
"2","AAA","BBB","","","","","","",""

$ cat newname2.csv
"1","4668","",""
"2","46","",""

尝试的代码及异常输出

用户最初的Perl代码运行后,CRLF的^M被保留为最后一个字段,导致输出异常:

#!/usr/bin/perl

use strict;
use warnings;

my %inputs = qw(
  file1 file1.txt
  file2 file2.txt
);

my %outputs = qw(
  file1 newname1.csv
  file2 newname2.csv
);

for my $key (keys %inputs) {
  
  open my $in, '<', $inputs{$key} or die $!;
  open my $out, '>', $outputs{$key} or die $!;
  
  while(<$in>) {
    local $, = ',';
    local $\ = "\n";
    s/\$$//;
    my @row = split /\$/;
    print $out map qq("$_"), @row;
  }
  
  close $in or die $!;
  close $out or die $!;
  
}

异常输出:

$ cat -v newname1.csv
"1","XXX","ZZZ","","","","","","","","","^M
"
"2","AAA","BBB","","","","","","","","","^M
"

$ cat -v newname2.csv
"1","4668","","","^M
"
"2","46","","","^M
"

用户尝试过的无效方案:

  • 改用<:crlf打开文件,结果无改善
  • 使用\$\r\n/\$\R匹配行尾$,导致丢失末尾空字段

解决方案

问题核心是CRLF的\r(即^M)未被正确清除,且split默认丢弃末尾空字段。修改后的代码如下:

#!/usr/bin/perl

use strict;
use warnings;

my %inputs = qw(
  file1 file1.txt
  file2 file2.txt
);

my %outputs = qw(
  file1 newname1.csv
  file2 newname2.csv
);

for my $key (keys %inputs) {
  
  # 用:crlf层自动将CRLF转换为LF,统一换行符
  open my $in, '<:crlf', $inputs{$key} or die $!;
  open my $out, '>', $outputs{$key} or die $!;
  
  while(<$in>) {
    chomp; # 移除行尾所有换行符(\r\n或\n),避免^M残留
    next if /^\s*$/; # 跳过空行,按需调整
    
    s/\$$//; # 移除行尾最后一个$
    # split第三个参数-1:强制保留所有末尾空字段
    my @row = split /\$/, $_, -1;
    
    # 拼接成标准CSV行
    my $csv_line = join ',', map { qq("$_") } @row;
    print $out "$csv_line\n";
  }
  
  close $in or die $!;
  close $out or die $!;
  
}

关键修改说明

  1. <:crlf打开文件:让Perl自动处理CRLF换行符,将其转换为LF,避免手动处理\r的麻烦
  2. chomp清除换行符:彻底移除行尾的\r和\n,确保后续正则只处理业务内容
  3. split /\$/, $_, -1:默认split会丢弃末尾的空字段,加上-1参数后会保留所有空字段,保证输出的空列数量正确
  4. 手动拼接CSV行:替代local $,的方式,逻辑更直观,减少隐式行为导致的问题

内容的提问来源于stack exchange,提问作者Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:25:04