-1

我正在尝试从 A 到 Z 对文件中的字母进行排序,例如: a AB drg sorted: A a B dgr

@ARGV == 2 or die "Usage: $0 infile outfile\n";
open $old,  '<', $ARGV[0] or die $!;
open $new, '>', $ARGV[1] or die $!;
@mass=<$old>;
@array=qw(@mass);
@sort=sort @array;
@mass1=sort {uc $a cmp uc $b} @sort;
print $new @mass1;

我哪里错了?

4

3 回答 3

3

我认为您不了解标准文本排序是基于 ASCII 的。因此,因为所有大写字母都继续小写字母,所以您的输入也是如此。因此,您订购顺子sort将是( 'A', 'B', 'a', 'd', 'g', 'r' )

您想双重比较两个字符串。在这种情况下,您将需要传递一个例程进行排序。

@sort= sort { lc $a cmp lc $b or $a cmp $b } @array;
于 2013-01-22T13:31:51.997 回答
2

我不确定您打算如何处理qw,但只要说@mass永远不会使用 的内容就足够了。

@array = qw(hello world);

将导致@array被定义为包含 2 个字符串helloworld。它只是以下的简写:

@array = ('hello', 'world');

这就是为什么

@array=qw(@mass);

计算为('@mass')- 具有 5 个字符的单个文字字符串的数组@mass

也许这就是你做错了。如果你尝试怎么办

@array = map { split /\s+/} @mass;

@mass是行列表。每行有单词或只有字母,用空格分隔。最后一行所做的是将每一行映射到split /\s+/- 这会将每一行拆分'ba ab a G'为一个列表('ba', 'ab', 'a', 'G')并将@array成为一个单词/字母列表。

然后就是你想如何对它们进行排序的问题。另请参阅其他答案。

哦,记得在写出文件时放回空格:

print $new (join " ", @mass1);

如果您希望每一行相互独立地排序,那也很容易:

$mass1 = join "\n", map { join " ", sort (split /\s+/) }  @mass

读作“对于 中的每一行@mass,在空间上拆分,排序并再次用空间连接回来”,并与结果数组一起,连接newline以产生文件的输出。

请注意,您可以使用类似等sort的比较器。sort { $a cmp $b }

如果您的文件太大,那么循环可能是谨慎的:

for my $mass (<$old>) {
    my $sorted_line = join " ", sort (split /\s+/, $mass);
    print $new "$sorted_line\n";
}
于 2013-01-22T13:27:10.830 回答
1

您需要找到要使用的正确 LOCALE,以便所有函数(排序等)使用的顺序都使用正确的语言环境并相应地进行排序。

请参阅此页面,其中显示了大多数定义 locales 的变量,并查找 LANG 和 LC_ALL。和 LC_COLLATE (我不得不承认我不确定何时使用哪个。LC_ALL 应该优先于其他人,所以你可以更改它以设置所有 LC_* 值...请测试,ymmv)

我相信您可能需要使用其中一种 unicode 语言环境。Ascii 不会做你想做的事,因为 CAPS 在 ascii 中的常规字母之前。

要找出可以使用的语言环境:locale -a

查看您当前设置的语言环境:(locale用户和系统范围的值是可能的)

您可能需要包含“utf-8”的内容才能获得您寻求的订单

然后:(如果例如 en_US.UTF-8 可用):

在排序中使用它之前,定义要排序的语言环境:

LC_ALL=en_US.UTF-8

(或您需要设置的任何值,并且可用,如“locale -a”所示)

(如果需要,在调用周围保存/恢复它们以前的值)

在 shell 中,您最好将“导出”到您重新定义的那些变量,以确保子 shell 也使用新值(例如::something | sort在 bash 中,sort将在子 shell 中,因此使用 LC_* 的默认值,或使用导出的值,如果你导出它!)

于 2013-01-22T13:59:06.383 回答