perl - perl 中的 Unicode,mkdir 练习

标签 perl unicode filesystems

我目前正在学习 Unicode 编程的艺术,并将其应用于个人项目。很快我就意识到很难做到正确,甚至很难理解你是否做得对:如果工具错了,你在评估工作结果时可能会出错。

我在这个练习中的小目标是了解我应该传递给 mkdir 的内容。与对 File::Path::make_path 有益的东西相比.换句话说:他们期望什么?他们会根据语言环境处理编码,还是我应该为他们处理?

我编写了以下脚本,它接受来自 @ARGV 的参数并为他们每个人创建目录$_ , 使用这两个函数以及编码和解码的 froms。

#!/usr/bin/perl

use warnings;
use strict;
use utf8;
use v5.16;

use Encode;
use Encode::Locale;

use File::Path qw/make_path/;
use File::Spec;

# Everything under the './tree' directory
mkdir 'tree';
mkdir File::Spec->catdir('tree', $_)
    for ('mkdir', 'mkdir_enc', 'make_path', 'make_path_enc');

foreach (map decode(locale => $_) => @ARGV) {
    mkdir File::Spec->catdir('tree', 'mkdir', $_);
    mkdir encode(locale_fs => File::Spec->catdir('tree', 'mkdir_enc', $_));

    make_path(File::Spec->catdir('tree', 'make_path', $_));
    make_path(encode(locale_fs => File::Spec->catdir('tree', 'make_path_enc', $_)));
}

我执行脚本如下:
./unicode_mkdir.pl a→b←c

我期望的是:
  • tree/mkdir [x] 或 tree/mkdir_enc包含名为 gibberish 的目录;
  • tree/make_path [x] 或 tree/make_path_enc包含名为 gibberish 的目录;

  • 我非常惊讶地发现所有版本都可以正常工作。我用 find 验证了它:
    $ find tree
    tree
    tree/mkdir_enc
    tree/mkdir_enc/a→b←c
    tree/mkdir
    tree/mkdir/a→b←c
    tree/make_path_enc
    tree/make_path_enc/a→b←c
    tree/make_path
    tree/make_path/a→b←c
    

    我意识到 tree命令让它变得如此错误......(一种很常见的疾病)但至少我可以看到结果都是一样的:
    $ tree tree
    tree
    ├── make_path
    │   └── a\342\206\222b\342\206\220c
    ├── make_path_enc
    │   └── a\342\206\222b\342\206\220c
    ├── mkdir
    │   └── a\342\206\222b\342\206\220c
    └── mkdir_enc
        └── a\342\206\222b\342\206\220c
    
    8 directories, 0 files
    

    一个 ls -R命令似乎证实了这一点。
    $ ls -R tree
    tree:
    make_path  make_path_enc  mkdir  mkdir_enc
    
    tree/make_path:
    a→b←c
    
    tree/make_path/a→b←c:
    
    tree/make_path_enc:
    a→b←c
    
    tree/make_path_enc/a→b←c:
    
    tree/mkdir:
    a→b←c
    
    tree/mkdir/a→b←c:
    
    tree/mkdir_enc:
    a→b←c
    
    tree/mkdir_enc/a→b←c:
    

    所以我的问题是:
  • 我在代码方面做得对吗(当然不是)?
  • 我在文件系统方面做得对吗?
  • 怎么可能mkdirmake_path找出并修复错误的?
  • 或者也许我只是“逆向幸运”(那种幸运不会让你意识到你的错误,因为在你的情况下呢?在那种情况下,我怎样才能有效地测试它?

  • 有什么提示吗?

    最佳答案

    1. How can mkdir and make_path figure out and fix the wrong one?


    Perl 字符串有一个“UTF-8 标志”,指示它们包含的“字符”是否是 Unicode 字符,而不是八位字节(八位字节)。您可以使用 utf8::is_utf8函数(见 http://perldoc.perl.org/utf8.html )检查是否为给定字符串设置了 UTF-8 标志;或者您可以使用 Dump来自 Devel::Peek模块,它打印出标量的所有内容,包括设置的标志列表。

    所以mkdirmake_path不需要做太疯狂的事;他们可以通过将 Unicode 字符串编码为八位字节字符串来处理它们,就像您在调用 encode 时所做的那样。 .

    (不幸的是,UTF-8 标志的东西有很多怪癖,并不是所有的函数都支持它;例如,encode 不关心它的参数是否设置了那个标志,它只是相信你不会调用它在一个字符串上,除非该字符串应该被解释为一个 Unicode 字符序列。但是,如果您使用现代的、支持 Unicode 的库和 use utf8 ,并且只做 Unicode-ishly 的所有事情,除非专门与面向字节的交互外部系统(你使用 Encode::encodeEncode::decode ),你应该没问题。)

    1. Am I doing it right code-wise ('course not)?
    2. Am I doing it right filesystem-wise?


    是的,除了我认为您应该更加注意错误情况。如果您的输入无法在语言环境字符集中表示怎么办?如果可以,但结果不是您的操作系统或文件系统中的有效文件名怎么办?

    要解决这个问题,您应该进行两到三个更改:
  • 您应该向 Encode::encode 提供显式的第三个参数指定它应该如何处理不可编码的字符。 (默认行为是用替换字符替换它们,例如 ? 用于 US-ASCII;这可能不是您想要的。)
  • 您应该检查 mkdir 的返回值.
  • 您可能想使用 error make_path 的选项,并检查生成的arrayref;或者,您可能想要包装 make_patheval堵塞。
  • 关于perl - perl 中的 Unicode,mkdir 练习,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36233493/

    相关文章:

    Android Chrome 无法通过文件系统 API 播放或加载视频

    database - 存储大量数据 : DB or File System?

    perl - 在 Perl 中生成引用第 3 方插件函数的 Excel 电子表格

    perl - Perl 中的嵌套解引用箭头 : to omit or not to omit?

    perl - 如何修复损坏的/'nonconformance to standards' PDF

    perl - 在 Perl/Moose 中,如何将修饰符应用于所有子类中的方法?

    Ruby system() 不接受 UTF-8?

    c# - StreamReader 无法正确读取扩展字符集 (UTF8)

    html - 如何控制(在所有设备和浏览器上)字符显示为表情符号版本还是文本版本?

    c# - 递归处理文件夹中文件的快速(低级)方法