我想知道为什么使用Perl构建的大多数现代解决方案默认情况下不启用UTF-8.
我知道核心Perl脚本存在许多遗留问题,可能会破坏它们.但是,从我的角度来看,在21 日的世纪,新的大项目(或具有大的方面讲项目)应该从头开始他们的软件UTF-8的证明.我仍然没有看到它发生.例如,Moose启用严格和警告,但不启用Unicode.Modern :: Perl也减少了样板,但没有UTF-8处理.
为什么?是否有一些理由在2011年的现代Perl项目中避免使用UTF-8?
评论@tchrist太长了,所以我在这里添加它.
似乎我没有说清楚.让我尝试添加一些东西.
tchrist和我看到情况非常相似,但我们的结论完全是相反的.我同意,Unicode的情况很复杂,但这就是为什么我们(Perl用户和编码人员)需要一些层(或编译指示),这使得UTF-8处理变得像现在一样容易.
tchrist指出要涵盖的许多方面,我会阅读并思考它们几天甚至几周.不过,这不是我的观点.tchrist试图证明没有一种方法"启用UTF-8".我没有太多的知识可以与之争辩.所以,我坚持住实例.
我和Rakudo一起玩,UTF-8就在我需要的地方.我没有任何问题,它只是奏效了.也许在某些地方存在一些限制,但一开始,我测试的所有工作都按照我的预期进行.
这不应该是现代Perl 5的目标吗?我更强调一点:我不是建议将UTF-8作为核心Perl的默认字符集,我建议可以为那些开发新项目的人快速触发它.
另一个例子,但更负面的语气.框架应该使开发更容易.几年前,我尝试过Web框架,但只是把它们扔掉了,因为"启用UTF-8"是如此模糊.我没有找到如何以及在何处挂钩Unicode支持.这是非常耗时的,我发现它更容易走老路.现在我看到这里有一个赏金来处理与梅森 2 相同的问题:如何让Mason2 UTF-8干净?.因此,它是一个非常新的框架,但使用UTF-8需要深入了解其内部.这就像一个大红色标志:停止,不要使用我!
我真的很喜欢Perl.但处理Unicode是痛苦的.我仍然发现自己在墙上奔跑.某种方式tchrist是正确的,并回答我的问题:新项目不吸引UTF-8,因为它在Perl 5中太复杂了.
在我的语言环境(et_EE)中[a-z]表示:
abcdefghijklmnopqrsšz
Run Code Online (Sandbox Code Playgroud)
因此,不包括6个ASCII字符(tuvwxy)和一个来自爱沙尼亚字母(ž).我看到很多模块仍在使用正则表达式
/\A[0-9A-Z_a-z]+\z/
Run Code Online (Sandbox Code Playgroud)
对我来说,似乎错误的方式来定义ASCII字母数字字符的范围,我认为它应该替换为:
/\A\p{PosixAlnum}+\z/
Run Code Online (Sandbox Code Playgroud)
第一个仍然被认为是惯用的方式吗?或接受解决方案?还是一个bug?
或者最后一个警告?
在Debian Jessie中,我安装了MariaDB服务器10.0.30,并尝试增加最大密钥长度.AFAIU取决于innodb_large_prefix启用的配置参数.根据文档,它还需要barracuda文件格式和innodb_file_per_table.在config中设置并重新启动服务器后,我在客户端看到,这些参数设置正确:
> SHOW GLOBAL VARIABLES LIKE 'innodb_large%';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| innodb_large_prefix | ON |
+---------------------+-------+
1 row in set (0.00 sec)
> SHOW GLOBAL VARIABLES LIKE 'innodb_file%';
+--------------------------+-----------+
| Variable_name | Value |
+--------------------------+-----------+
| innodb_file_format | Barracuda |
| innodb_file_format_check | OFF |
| innodb_file_format_max | Antelope |
| innodb_file_per_table | ON |
+--------------------------+-----------+
4 rows in set (0.00 sec)
> SHOW GLOBAL VARIABLES LIKE …Run Code Online (Sandbox Code Playgroud) 是什么原因,在纯UTF-8环境中使用CONCAT()MySQL仍然将连接字符串(当表达式中的某些col为例如int或date)视为其他字符集(可能是Latin-1)?
从client(\s)看到的MySQL环境:
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
Run Code Online (Sandbox Code Playgroud)
测试数据集:
CREATE TABLE `utf8_test` (
`id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(50) collate utf8_estonian_ci default NULL,
`year` smallint(4) unsigned NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_estonian_ci;
INSERT INTO utf8_test VALUES (1, 'Õäöüšž', 2011);
Run Code Online (Sandbox Code Playgroud)
这个查询很好:
SELECT id, title FROM utf8_test;
Run Code Online (Sandbox Code Playgroud)
这个关闭utf-8标志(已经在MySQL,AFIU):
SELECT CONCAT(id, title) FROM utf8_test;
Run Code Online (Sandbox Code Playgroud)
从mysql-client看来一切都很好,因为它设置为将字符显示为UTF-8,但是当通过perl DBI运行时,所有内部有CONCAT()的查询结果都没有设置utf-8标志.示例代码:
#!/usr/bin/perl
use strict;
use utf8::all;
use Encode qw(is_utf8);
my $dbh = …Run Code Online (Sandbox Code Playgroud) 有几次我遇到了忘记Try::Tiny在脚本中加载模块而仍然使用它的代码try-catch块的情况,如下所示:
#!/usr/bin/env perl
use strict;
use warnings;
try {
call_a( 'x' );
} catch {
die "ACTUALLY die $_";
};
sub call_a {
die "Yes, I will";
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,该脚本可以正常运行,而没有任何提示try。没有Undefined subroutine错误。这使我想知道为什么未捕获我提出的异常。
为什么这会无声地工作而没有错误?
编辑
我也查看了符号表:
say "$_: %main::{ $_ }" for keys %main::;
Run Code Online (Sandbox Code Playgroud)
没有发现try。我也尝试像main::try上面的脚本一样调用它,它也没有引起错误。
我试图更好地理解异常的逻辑和流程.所以我得说明,我真的感到缺乏理解Perl如何解释和运行程序,涉及哪个阶段以及每个阶段会发生什么.
例如,我想了解,什么时候绑定STD*IO并在发布时,$ SIG {*}事情发生了什么,它们如何依赖于例外,程序如何死亡等等.我想要更好地了解内部机械.
我正在寻找链接或书籍.我更喜欢一些也有视觉图表的材料,但这不是强制性的.我希望看到整个过程的"大局",如果我认为有必要,我已经有可能进一步挖掘.
我发现编程Perl中的第18章给出了编译阶段的概述,我尝试将其工作,但我也很欣赏其他好的资源.
从我之前的问题为什么在locale-pragma字符下不匹配?以及如何更改嵌套引号我了解到,在处理UTF-8数据时,您不能信任\wword-char,必须使用Unicode字符属性\p{Word}.现在,我发现零宽度字边界\b也不适用于UTF-8(启用了区域设置),但我没有在Unicode字符属性中找到任何等效字符.我以为我可以自己构建它:(?<=\P{Word})(\p{Word}+)(?=\P{Word})它应该等同于\b(\w+)\b.
在下面的测试脚本中,我有两个数组来测试两个不同的正则表达式.\b当未启用语言环境时,第一个基于工作正常.为了使它也能与locales一起工作,我编写了另一个带有模拟边界的版本,(?=\P{Word})但是它没有按照我的预期工作(我也在脚本中显示了预期的结果).
你是否看到了什么错误以及如何使用ASCII(或没有语言环境)来模拟正则表达式的工作?
#!/usr/bin/perl
use 5.010;
use utf8::all;
use locale; # et_EE.UTF-8 in my case
$| = 1;
my @test_boundary = ( # EXPECTED RESULT:
'"abc def"', # '«abc def»'
'"abc "d e f" ghi"', # '«abc «d e f» ghi»'
'"abc "d e f""', # '«abc «d e f»»'
'"abc "d e f"', # '«abc "d e f»'
'"abc "d" "e" …Run Code Online (Sandbox Code Playgroud) 有Perl模块名称,如Moose和MooseX或DBI和DBIx或Catalyst和CatalystX或Mojo和MojoX或PPI和PPIx等.
X后缀是什么意思?
我想导入package.json到test.js,两个文件都在同一目录中。
我尝试过require:
const jsonfile = require("./packages.json");
console.log({ jsonfile });
Run Code Online (Sandbox Code Playgroud)
它抛出错误:
file:///home/.../test.js:1
const jsonfile = require("./packages.json");
^
ReferenceError: require is not defined
at file:///home/.../test.js:1:18
at ModuleJob.run (internal/modules/esm/module_job.js:145:37)
at async Loader.import (internal/modules/esm/loader.js:182:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
Run Code Online (Sandbox Code Playgroud)
这个错误意味着,就像它在浏览器中运行一样,其中 no require,我找到了带有类似消息的答案。
我尝试过import:
import * as jsonfile from './packages.json';
console.log({ jsonfile });
Run Code Online (Sandbox Code Playgroud)
internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/.../packages.json' imported from /home/.../test.js
at finalizeResolution (internal/modules/esm/resolve.js:271:11)
at moduleResolve (internal/modules/esm/resolve.js:694:10)
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:784:11) …Run Code Online (Sandbox Code Playgroud) 我想在字符串中捕捉罗马数字(80以下的数字足够好).我找到了很好的基础,你如何只使用正则表达式匹配有效的罗马数字?.问题是:它处理整个字符串.我还没有找到如何检测字符串内的罗马数字的解决方案,因为没有强制要求,每个组都可以是可选的.到目前为止我尝试过这样的事情:
my $x = ' some text I-LXIII iv more ';
if ( $x =~ s/\b(
(
(XC|XL|L?X{0,3}) # first group 10-90
|
(IX|IV|V?I{0,3}) # second group 1-9
)+
)
\b/>$1</xgi ) { # mark every occurrence
say $x;
}
__END__
><some>< ><text>< ><>I<><-><>LXIII<>< ><>iv<>< ><more><
desired output:
some text >I<->LXIII< >iv< more
Run Code Online (Sandbox Code Playgroud)
因此,这个也可以自己捕获字边界,因为所有组都是可选的.如何完成它?如何强制执行这两个组中的一组,而无法确定哪一组是强制性的?其他捕捉罗马人的方法也很受欢迎.