在使用特定字段中的数字进行排序时,如何创建sort
或忽略字母?awk
我的文本文件中有以下数据:
name name space 2018
name2 name2 space (active 2020)
name1 name1 space (c. 2019)
我希望该命令忽略“(”、“)”、“c.”和“active”,因此它可以仅使用年份对数据进行排序。
我正在寻找这个输出:
name name space 2018
name1 name1 space (c. 2019)
name2 name2 space (active 2020)
答案1
提取最后一个字段的适当部分,并将其添加为独立的可排序字段。在该字段上排序。删除临时添加的字段,这样我们就只剩下原始数据
awk '{y = $NF; gsub("[^[:digit:]]", "", y); printf "%s\t%s\n", y, $0}' file |
sort -k1,1n |
cut -f2-
包含gsub
一个 RE,用于删除最后一个空格分隔字段中的所有非数字字符。您可以仅运行该awk
命令(显然没有尾随管道字符)来查看它对输入数据的作用。然后添加sort
看看会发生什么。
答案2
要对每行最右边的十进制数字序列进行排序,您可以将其提取出来并将其放在前面,然后进行排序和剥离:
<file LC_ALL=C sed '
h; # save pattern space (current line) onto hold space
s/[^0123456789]*$//; # remove non-digit characters from the end
s/^.*[^0123456789]//; # remove everything up to the last non-digit
G; # append \n and hold space to pattern space
s/\n/:/; # replace that \n with :' |
sort -n |
cut -d: -f2-
答案3
应用选项-V
(自然排序)并按第一个字段排序
sort -Vk1,1 file
name name space 2018
name1 name1 space (c. 2019)
name2 name2 space (active 2020)
对于一些棘手的情况:
sort -Vk1,1 -k5 file
听完评论,我决定补充一下:
awk 'BEGIN {PROCINFO["sorted_in"]="@val_num_asc"} {a=$0; gsub(/[^0-9]/, ""); D[a]=$0}; END {for(i in D)print i}' file
我将所有数字传输到带有字符串形式的键的数组的值并指定排序顺序:
PROCINFO["sorted_in"]="@val_num_asc"
答案4
使用 Raku(以前称为 Perl 6)
这比看起来更困难。我首先将测试文件中的行数加倍,然后考虑解决此问题的最佳方法。一种方法可能是按空格进行拆分,但也会按括号内的空格进行拆分,因此某些行将有 4 列,而其他行将有 5 列。
下面的代码对 4 位“年份”正则表达式进行排序,忽略列(即“文本字段”,用 OP 的说法)。只要每行只有一 (1) 年,该代码就可以工作:
raku -e 'my $a = lines(); my @b = $a.comb(/ \d**4 /).pairs; my $c = @b.sort(*.values)>>.keys.flat; $a[$c.flat]>>.put;' sort_year.txt
name name space 2018
name0 name space 2018
name1 name1 space (c. 2019)
name4 name1 space (c. 2019)
name2 name2 space (active 2020)
name3 name2 space (active 2020)
上面的代码梳理了 4 位正则表达式模式 ( @b
);排序索引 ( $c
) 导出(来自@b
),然后$a
根据索引“键” ( $c
) 对行 ( ) 重新排序。
这是输入文件,供任何想在家尝试的人使用:
~$ cat sort_year.txt
name name space 2018
name2 name2 space (active 2020)
name1 name1 space (c. 2019)
name0 name space 2018
name3 name2 space (active 2020)
name4 name1 space (c. 2019)