我有一个混乱的文件内容如下:
13,13,GAME_FINISH,
1,1,GAME_START,
1,1,GROUP_FINISH,
17,17,WAGER,200.00
2,2,GAME_FINISH,
2,2,GAME_START,
22,22,GAME_WIN,290.00
2,2,GROUP_FINISH,
32,32,WAGER,200.00
3,3,GAME_FINISH,
3,3,GAME_START,
.... more lines
我对它进行了排序,目前按以下格式保存文件内容:
1,1,GAME_FINISH,
1,1,GAME_START,
1,1,GROUP_FINISH,
1,1,WAGER,200.00
2,2,GAME_FINISH,
2,2,GAME_START,
2,2,GAME_WIN,290.00
2,2,GROUP_FINISH,
2,2,WAGER,200.00
3,3,GAME_FINISH,
3,3,GAME_START,
3,3,GROUP_FINISH,
3,3,WAGER,200.00
... more lines
但是我怎样才能更好地排序以获得以下格式?第3和第4行可能并不总是存在。
1,1,WAGER,200.00
1,1,GAME_START,
1,1,GAME_WIN,500.00
1,1,BONUS_WIN_1,1100.00
1,1,GAME_FINISH,
1,1,GROUP_FINISH,
2,2, more lines...
对于初始排序,我使用了
sort -t, -g -k2 nameofunsortedfile.csv >> sortedfile.csv
添加信息:
我想按此顺序排序 - 下注,游戏开始,游戏获胜,奖金获胜,游戏结束,小组完成。我当前的排序不按此顺序排列。游戏胜利和奖金获胜可能并不总是存在。
我期待的顺序不是字典,也不是随机的。每个数字总是有一个赌注,开始,game_finish group_finish序列。 game_win,game_bonus是可选的。寻找一种方法来举例说明在所提到的预期序列中进行1,1排序,继续进行2,2做同样的事情等等。
答案 0 :(得分:2)
使用标准UNIX实用程序执行此操作的最直接方法可能是为每行添加一个附加字段,该字段按照您想要的顺序对记录类型进行编码。
declare -A mapping=( ["WAGER"]=1 ["GAME_START"]=2 ["GAME_WIN"]=3 ["BONUS_WIN"]=4 ["GAME_FINISH"]=5 ["GROUP_FINISH"]=6 )
cut -d, -f3 filename.txt | while read; do echo ${mapping["$REPLY"]}; done | paste -d, - filename.txt | sort | sort -s -t, -n -k 2,3 | cut -d, -f 2-
declare
语句声明了一个映射,允许您查找每种记录类型的顺序。只要符合您想要的顺序,具体值(1
,2
等)就不重要了;如果您愿意,可以使用字母或单词。
然后下一行包含以下命令:
cut -d, -f3 filename.txt
提取您要按(WAGER
或其他)while read; do echo ${mapping["$REPLY"]}; done
获取每个值(WAGER
等),并将其替换为关联数组mapping
paste -d, - filename.txt
将这些值重新粘贴到filename.txt
sort | sort -s -t, -n -k 2,3
具有按字段2排序的效果,然后是字段3,然后是字段1(我们添加的字段)。如果sort
可以使用三个字段作为键,我们可以在一个sort
命令中执行此操作,但它最多只接受两个字段进行排序。cut -d, -f 2-
剥离添加的字段,为您留下原始记录,但按排序顺序答案 1 :(得分:1)
Perl救援:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $i = 1;
my %order = map { $_ => $i++ }
qw( WAGER GAME_START GAME_WIN BONUS_WIN GAME_FINISH GROUP_FINISH );
chomp( my @lines = <> );
say join ',', @$_ for sort {
$a->[0] <=> $b->[0]
|| $order{ $a->[2] } <=> $order{ $b->[2] }
} map [ split /,/ ], @lines;
sort块告诉Perl首先按第一列排序,如果值相同,请使用与第三列对应的“order”。