PERL:从A到Z的字母排序

时间:2013-01-22 13:15:35

标签: perl file sorting

我正在尝试将文件中的字母从A到Z排序 例如:a A B d r g 排序:A a B d g r

@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;

我哪里错了?

3 个答案:

答案 0 :(得分:3)

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

您希望 double 比较两个字符串。在这种情况下,您将需要传递例程进行排序。

@sort= sort { lc $a cmp lc $b or $a cmp $b } @array;

答案 1 :(得分: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";
}

答案 2 :(得分:1)

您需要找到要使用的正确LOCALE,以便所有函数使用的顺序(排序等)使用正确的区域设置并相应地进行排序。

请参阅this page showing most of the variables defining 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将在subshel​​l,因此使用默认值LC_ *,或者在导出时使用导出值!)