根据ASCII值分割字符串

时间:2019-08-28 09:43:28

标签: perl ascii

我需要解析一个定界文件(由大型机作业生成并通过ftp传输到Windows)。但是在定界符上进行分割时, Q 项很少。

根据文档,文件由'1D'分隔。但是,当我在记事本++中打开文件时(当我检查编码选项卡时,将其设置为“在ANSI中编码” ),在我看来,这就像是一个“垂直折线”。 Q 。不确定什么是“一维”?

enter image description here

open my $handle, '<', 'sample.txt';
chomp(my @lines = <$handle>);
close $handle;
my @a = unpack("C*", $lines[0]);
print Dumper \@a;
# $VAR1 = [65,166,66,166,67,166];

从转储器的输出中,我们看到perl认为垂直折线的ASCII为166。

根据link1,确实是166个垂直虚线,而根据link2,则是166个女性的序号指示符。问。关于为什么存在差异的任何建议? / p>

my $str = $lines[0];
print Dumper $str;
# $VAR1 = 'AªBªCª';

我们可以看到输出包含“女性顺序指示符”而不是“垂直折线”。问。不确定为什么perl会读取“ bar”,然后开始将其视为其他内容。< / p>

# I copied the vertical broken bar from notepad++ for use below
my @b = split(/¦/, $lines[0]);
print Dumper \@b;
# $VAR1 = [ 'AªBªCª' ];

由于perl开始像预期的那样将bar视为其他东西,因此这里没有拆分。我想通过直接给出166的ascii代码来拆分。似乎split()不支持ASCII作为参数。 Q 。将ASCII代码传递给split()的任何解决方法?

# I copied the vertical broken bar from notepad++ and created A¦B¦C
my @c = split(/¦/, 'A¦B¦C');
print Dumper \@c;
#$VAR1 = [ 'A','B','C']; # works as expected, added here just for completion

任何指针都会有很大帮助!

Update:
my @a = map {ord $_} split //, $lines[0]; print Dumper \@a;
# $VAR1 = [ 65,166,66,166,67,166];

2 个答案:

答案 0 :(得分:2)

当您从未知来源收到输入文件时,最需要了解的是“它使用什么字符编码?”。没有这些信息,您对文件所做的任何处理都是基于猜测。

谈论“扩展的ASCII”的人并没有解决该问题,尽管这是一个有意义的术语。 ASCII仅包含128个字符。接下来的128个字符代码代表什么定义,其中很多是矛盾的。

看来您有解决问题的办法。在“ ¦”(从Notepad ++复制)上拆分即可满足您的需求。所以我建议你这样做。如果要使用实际的字符代码,则可以将116转换为十六进制(0xA6)并使用:

split /\xA6/, ... ;

答案 1 :(得分:2)

您应该始终解码输入并编码输出。

my $acp;
BEGIN {
   require Win32;
   $acp = "cp".Win32::GetACP();
}

use open ':std', ":encoding($acp)";

现在,@lines将包含Unicode代码点的字符串。这样,您现在可以使用以下内容:

use utf8;  # Source code is encoded using UTF-8.
my @b = split(/¦/, $lines[0]);

或者,以下每个选项现在也都可以使用:

my @b = split(/\N{BROKEN BAR}/, $lines[0]);
my @b = split(/\N{U+00A6}/, $lines[0]);
my @b = split(/\x{A6}/, $lines[0]);
my @b = split(/\xA6/, $lines[0]);