我正在尝试从a到Z排序文件中的字母例如:a a B d r g排序:A A B d g r
@ARGV == 2 or die "Usage: $0 infile outfilen";
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;
我哪里错了?
我认为您不了解标准文本排序是基于ascii的。因为所有的大写字母都是小写的,所以输入也是如此。因此,你直接订购的sort
就是( 'A', 'B', 'a', 'd', 'g', 'r' )
。
要double比较两个字符串。在本例中,您将需要传递一个例程来排序。
@sort= sort { lc $a cmp lc $b or $a cmp $b } @array;
我不确定你打算用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_linen";
}
您需要找到要使用的正确LOCALE,以便所有函数(sort等)使用的顺序都使用正确的LOCALE并据此进行排序。
请参阅这个页面,其中显示了大多数定义区域设置的变量,并查找LANG和LC_ALL。和LC_COLLATE(我不得不承认,我不太确定在什么时候使用哪个)。LC_ALL应该优先于其他的,所以你可以改变它来设置所有的LC_*值…请测试,ymmv)
我相信您可能需要使用unicode区域设置之一。Ascii不会做你想要的,因为在Ascii中,大写字母在常规字母之前。
查找可以使用的语言环境:locale -a
查看当前设置的区域设置:locale
(用户和系统范围的值是可能的)
你可能需要一些包含"utf-8"的东西来获得你寻找的顺序
Then:(例如en_US。UTF-8可用):
在排序中使用它之前,定义要使用的区域设置:
LC_ALL=en_US.UTF-8
(或您需要设置的任何值,如"locale -a"所示)
(如果需要,保存/恢复调用前后的值)
在shell中,您可能最好将"export"添加到您重新定义的变量中,以确保子shell也使用新值(例如:something | sort
:在bash中,sort
将在子shell中,因此使用默认值LC_*,或者使用导出值,如果您导出了它!)