我正在尝试将文件中的字母从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;
我哪里错了?
答案 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个字符串,hello
和world
。它只是简写:
@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
将在subshell,因此使用默认值LC_ *,或者在导出时使用导出值!)