如何使用Sed或Perl根据字符串的第二列号以降序对给定的文本文件进行排序
Input.txt
123|N1-G23-H40-K1-A11-C12-J12|banana|boy
123|Z12|Goal|test
123|F1-B23-G39-M22-Z12|some|girl
123|E1-T23-N12|car|girl
123|N1-G23-H40-K1-A11-C12|banana|boy
123|V1-M12|car|girl
123|P1-G23-H40-K1|school|boy
Output.txt
123|N1-G23-H40-K1-A11-C12-J12|banana|boy
123|N1-G23-H40-K1-A11-C12|banana|boy
123|F1-B23-G39-M22-Z12|some|girl
123|P1-G23-H40-K1|school|boy
123|E1-T23-N12|car|girl
123|V1-M12|car|girl
123|Z12|Goal|test
答案 0 :(得分:0)
使用Schwartzian Transform
中的Perl
,请尝试以下操作:
perl -e '
print map { $_->[0] }
sort { $b->[1] <=> $a->[1] }
map { [$_, length((split(/\|/))[1])] }
<>;
' input.txt
输出:
123|N1-G23-H40-K1-A11-C12-J12|banana|boy
123|N1-G23-H40-K1-A11-C12|banana|boy
123|F1-B23-G39-M22-Z12|some|girl
123|P1-G23-H40-K1|school|boy
123|E1-T23-N12|car|girl
123|V1-M12|car|girl
123|Z12|Goal|test
[工作原理]
要了解算法,阅读脚本会很方便 从底部到顶部。
第一个功能:
map { [$_, length((split(/\|/))[1])] }
<>;
读取输入文件,然后生成保存输入行的二维列表 本身在第一列中,第二列的长度在第二列中 像这样:
[["123|N1-G23-H40-K1-A11-C12-J12|banana|boy\n", 25],
["123|Z12|Goal|test\n", 3],
["123|F1-B23-G39-M22-Z12|some|girl\n", 13],
...]]
第二个功能:
sort { $b->[1] <=> $a->[1] }
通过第二列中的值对列表进行排序 按降序排列,结果将如下所示:
[["123|N1-G23-H40-K1-A11-C12-J12|banana|boy\n", 25],
["123|N1-G23-H40-K1-A11-C12|banana|boy\n", 21],
["123|F1-B23-G39-M22-Z12|some|girl\n", 18],
...]]
最终功能:
print map { $_->[0] }
提取第一列并打印结果。
Schwartzian transform
是一种有用且高效的技术(或成语)
按列表元素的某个属性对列表进行排序。
答案 1 :(得分:0)
一种方法:
$ awk -F'|' -v OFS='|' '{ print $1, split($2, a, /-/), $2, $3, $4 }' input.txt |
sort -t'|' -k 2nr,3 |
cut -d'|' -f1,3,4,5
123|N1-G23-H40-K1-A11-C12-J12|banana|boy
123|N1-G23-H40-K1-A11-C12|banana|boy
123|F1-B23-G39-M22-Z12|some|girl
123|P1-G23-H40-K1|school|boy
123|E1-T23-N12|car|girl
123|V1-M12|car|girl
123|Z12|Goal|test
awk
位添加一个新的第二列,该列是原始第二列中用-
分隔的单词数。 sort
然后通过首先以相反的数字顺序对新的第二列进行排序来对输出进行排序,对于该数字相同的每一行,以升序的字典顺序对第三列(原始第二列)进行排序。最后,cut
删除了该多余的列。