【问题标题】:Perl - Encoding error when working with .html filePerl - 使用 .html 文件时出现编码错误
【发布时间】:2021-12-15 19:49:23
【问题描述】:

我在一个目录中有一些.html 文件,我想在其中添加一行css 代码。使用perl,我可以使用正则表达式定位位置并添加css 代码,效果很好。

但是,我的第一个 .html 文件包含重音字母:é,但生成的 .html 文件存在编码问题并打印:\xE9

在perl文件中,我在打开和关闭文件时一直小心指定UTF-8编码,在下面的MWE中有显示,但这并不能解决问题。如何解决此编码错误?

MWE

use strict;
use warnings;
use File::Spec::Functions qw/ splitdir rel2abs /; # To get the current directory name

# Define variables
my ($inputfile, $outputfile, $dir);

# Initialize variables
$dir = '.';

# Open current directory
opendir(DIR, $dir);

# Scan all files in directory
while (my $inputfile = readdir(DIR)) {
    
    #Name output file based on input file
    $outputfile = $inputfile;
    $outputfile =~ s/_not_centered//;
    
    # Open output file
    open(my $ofh, '>:encoding(UTF-8)', $outputfile);

    # Open only files containning ending in _not_centered.html
    next unless (-f "$dir/$inputfile");
    next unless ($inputfile =~ m/\_not_centered.html$/);
    
    # Open input file
    open(my $ifh, '<:encoding(UTF-8)', $inputfile);
    
    # Read input file
    while(<$ifh>) {
        # Catch and store the number of the chapter
        if(/(<h2)(.*?)/) {
            # $_ =~ s/<h2/<h2 style="text-align: center;"/;
            print $ofh "$1 style=\"text-align: center;\"$2";
        }else{
            print $ofh "$_";
        }
    }
    
    # Close input and output files
    close $ifh;
    close $ofh;
}

# Close output file and directory
closedir(DIR);

名为“Chapter_001_not_centered.html”的有问题的文件

<html > 
<head></head>
<body>
                                                           
<h2 class="chapterHead"><span class="titlemark">Chapter&#x00A0;1</span><br /><a id="x1-10001"></a>Brocéliande</h2>
Brocéliande

</body></html>

【问题讨论】:

  • HTML 文件是用 UTF-8 编码还是其他字符集?
  • 0xe9 for é 可能表示 HTML 文件不是 Unicode 编码的,而是使用一些扩展的 ASCII 代码页,如 Windows-1252 (CP-1252) 或 ISO 8859-1 (ISO Latin-1)。所以 UTF-8 在这里无济于事。
  • 啊!我忘了检查。根据记事本++,它在 ISO 8859-1 中我可以转换它吗?
  • 通过将打开和关闭文件的编码更改为ISO 8859-1,它解决了问题。如果你们中的一个人想发布答案,我会验证它。
  • Re "我可以转换它吗?",要么把它转换成你的程序所期望的(UTF-8),要么改变你的程序来期望它是什么(iso- 8859-1)

标签: perl encoding


【解决方案1】:

以下演示脚本确实需要 inject 并使用 glob 函数。

注意:脚本创建一个新文件,取消注释重命名以用新文件替换原始文件

use strict;
use warnings;

use open ":encoding(Latin1)";

my $dir = '.';

process($_) for glob("$dir/*_not_centered.html");

sub process {
    my $fname_in  = shift;
    my $fname_new = $fname_in . '.new';
    
    open my $in, '<', $fname_in
        or die "Couldn't open $fname_in";
        
    open my $out, '>', $fname_new
        or die "Couldn't open $fname_new";
        
    while( <$in> ) {
        s/<h2/<h2 style="text-align: center;"/;
        print $out $_;
    }
    
    close $in;
    close $out;

    # rename $fname_new, $fname_in
    #    or die "Couldn't rename $fname_new to $fname_in";

}

如果您不介意在每个文件的基础上运行以下脚本 script.pl in_file &gt; out_file

use strict;
use warnings;

print s/<h2/<h2 style="text-align: center;"/ ? $_ : $_ for <>;

如果这样的任务只是偶尔出现,那么可以用一个班轮解决

perl -pe "s/<h2/<h2 style='text-align: center;'/" in_file

【讨论】:

  • 谢谢,但正如您第一次发表评论之前的 cmets 所示,Shawn 和sticky bit 提供了答案
  • 你的脚本有很多不需要的代码,这个脚本演示了更简洁的方法。
【解决方案2】:

这个问题在@Shawn和@sticky bit的评论里找到了答案:

通过将打开和关闭文件的编码更改为 ISO 8859-1,它解决了这个问题。如果你们中的任何一个想发布答案,我会验证它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2017-09-03
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 2013-07-11
    • 2015-01-31
    相关资源
    最近更新 更多