使用Perl脚本实现CSV词表匹配替换XML文件中中文短语为英文
我来帮你把这个Perl脚本补全,实现从CSV双语词表替换XML里中文短语为英文的功能~先给你梳理下核心要解决的问题,再给出完整的实现代码:
完善后的Perl脚本实现
我们需要搞定几个关键环节:
- 正确读取CSV词表,构建中文到英文的映射关系
- 安全处理XML内容替换(避免破坏XML的标签结构)
- 统一编码,防止中文乱码
依赖模块说明
为了更稳妥地处理CSV和XML,建议安装两个CPAN模块(如果还没装的话):
Text::CSV:专门解析CSV文件,能处理包含逗号、引号的中文短语XML::LibXML:安全解析修改XML,比直接正则替换更可靠,不会破坏标签结构
用cpanm安装的命令如下:
cpanm Text::CSV XML::LibXML
完整脚本代码
use Cwd; use File::Basename; use File::Copy; use strict; use warnings; use Text::CSV; use XML::LibXML; use Encode qw(decode encode); # 配置文件路径,替换成你实际的文件名 my $DIR = '/Users/moody/Desktop/chinese/'; my $csv_path = "$DIR/glossary.csv"; my $xml_path = "$DIR/source.xml"; my $xml_backup_path = "$xml_path.bak"; # 1. 读取CSV词表,构建中文→英文的映射哈希 my %glossary; my $csv = Text::CSV->new({ binary => 1, sep_char => ',', # 如果你的CSV用制表符分隔,改成"\t"即可 auto_diag => 1, # 自动输出CSV解析错误,方便排查问题 }) or die "初始化CSV解析器失败: " . Text::CSV->error_diag(); open my $csv_fh, '<:encoding(UTF-8)', $csv_path or die "打不开CSV文件 $csv_path: $!"; # 如果CSV有表头,就跳过第一行;没有的话注释掉这行 $csv->getline($csv_fh); while (my $row = $csv->getline($csv_fh)) { my ($chinese, $english) = @$row; # 去除短语前后的空白字符 $chinese = trim($chinese); $english = trim($english); # 只添加有效条目 $glossary{$chinese} = $english if $chinese && $english; } close $csv_fh; # 2. 处理XML文件:替换中文短语为英文 # 先备份原文件,防止操作失误 copy($xml_path, $xml_backup_path) or die "备份XML文件失败: $!"; # 解析XML文档 my $parser = XML::LibXML->new({ encoding => 'UTF-8', load_ext_dtd => 0, # 不需要加载DTD的话可以关闭,提升速度 }); my $doc = $parser->parse_file($xml_path); # 遍历所有文本节点,只替换文本内容,不碰标签 my $xpc = XML::LibXML::XPathContext->new($doc); foreach my $text_node ($xpc->findnodes('//text()')) { my $content = $text_node->data; # 按短语长度从长到短替换,避免短短语先替换导致长短语匹配失败(比如先换"苹果"就会破坏"苹果手机"的匹配) foreach my $chinese (sort { length($b) <=> length($a) } keys %glossary) { $content =~ s/\Q$chinese\E/$glossary{$chinese}/g; } $text_node->setData($content); } # 保存修改后的XML文件,第二个参数1表示格式化输出,让XML更易读 $doc->toFile($xml_path, 1); print "替换完成!原XML文件已备份为 $xml_backup_path\n"; # 辅助函数:去除字符串前后的空白 sub trim { my $str = shift; $str =~ s/^\s+|\s+$//g; return $str; }
关键细节说明
- CSV处理:用
Text::CSV代替手动分割字符串,能兼容各种复杂的CSV格式(比如带引号的短语),同时指定UTF-8编码确保中文读取正确。 - XML处理:用
XML::LibXML只修改文本节点,完全不会破坏XML的标签结构,比直接正则替换整个XML文件安全得多。 - 替换顺序:按短语长度从长到短排序替换,避免短短语提前替换破坏长短语的匹配。
- 编码一致性:所有文件读写都指定UTF-8编码,彻底避免中文乱码问题。
- 文件备份:修改前自动备份原文件,不怕操作失误丢失数据。
简化版(无需XML模块的场景)
如果你的XML结构非常简单,且中文短语都不在标签属性里,也可以用直接读写文件+正则替换的方式,代码更简洁:
use Cwd; use File::Basename; use File::Copy; use strict; use warnings; use Text::CSV; use Encode qw(decode encode); my $DIR = '/Users/moody/Desktop/chinese/'; my $csv_path = "$DIR/glossary.csv"; my $xml_path = "$DIR/source.xml"; my $xml_backup_path = "$xml_path.bak"; # 读取CSV构建词表 my %glossary; my $csv = Text::CSV->new({ binary => 1, sep_char => ',', auto_diag => 1 }); open my $csv_fh, '<:encoding(UTF-8)', $csv_path or die "打不开CSV文件: $!"; $csv->getline($csv_fh); # 跳过表头 while (my $row = $csv->getline($csv_fh)) { my ($cn, $en) = map { trim($_) } @$row; $glossary{$cn} = $en if $cn && $en; } close $csv_fh; # 备份原文件 copy($xml_path, $xml_backup_path) or die "备份失败: $!"; # 读取XML内容并替换 open my $xml_fh, '<:encoding(UTF-8)', $xml_path or die "打不开XML文件: $!"; my $content = do { local $/; <$xml_fh> }; close $xml_fh; # 按短语长度从长到短替换 foreach my $cn (sort { length($b) <=> length($a) } keys %glossary) { $content =~ s/\Q$cn\E/$glossary{$cn}/g; } # 写入修改后的内容 open my $xml_out_fh, '>:encoding(UTF-8)', $xml_path or die "写入XML失败: $!"; print $xml_out_fh $content; close $xml_out_fh; print "替换完成,原文件备份为 $xml_backup_path\n"; sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s; }
注意:这个简化版可能会误替换标签属性里的中文(如果有的话),所以优先推荐用XML解析模块的方式。
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

