![](/img/trans.png)
[英]How to sort a CSV with quoted fields (that may contain the separator)
[英]How to sort on Multiple Fields with different field separator
我想对多个字段和多个字段分隔符上的文件进行排序。 请帮忙。 这是我的示例数据文件:
$ cat Data3
My Text|50002/100/43
My Message|50001/100/7
Help Text|50001/100/7
Help Message|50002/100/11
Text Message|50001/100/63
Visible Text|50001/100/52
Invisible Text|50002/100/1
第一个字段分隔符是管道符号,第二个字段分隔符是/
。 我想首先在第二个字段上对这些数据进行排序,然后在其中将数据按最后一个字段的排序顺序(用/
分隔)。 最后,我的排序数据应如下所示:
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43
通过使用sort -k2,2n -t'|'
,我可以对字段2( 50001/50002
)进行排序,但是在该值内,如何对最后一个字段(由/
分隔)进行排序?
此数据集的最简单技巧是将第二列视为版本号。
$ cat Data3 | sort -k2,2V -t'|'
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43
但是,根据您的输入,这并不总是有效。 这将起作用,因为第二列中的值相同。
您可以执行fedorqui的建议并运行两次排序,第二次进行稳定排序。 在联机帮助页中:-s,--stable(通过禁用最后查询比较来稳定排序)
首先对次要排序标准进行排序。 然后执行稳定的排序,这将使排序顺序保持在与主要排序条件共享相同键的行中。
$ cat Data3 | sort -k3,3n -t'/' | sort -k2,2n -t'|' -s
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43
在这种情况下,您很幸运,因为-k2,2n -t'|' 会将第二列“ 50001/100/7”视为一个数字,可能是50001。如果将逗号分隔而不是斜杠并且在环境中使用了不同的语言环境,则可能会遇到奇怪的情况。 例如,在我的环境中,默认情况下,我运行en_US.UTF-8,其行为如下。
$ cat Data3 | tr '/' ',' | sort -k3,3n -t',' | LC_NUMERIC=en_US.UTF-8 sort -k2,2n -t'|' -s
Help Text|50001,100,7
My Message|50001,100,7
Invisible Text|50002,100,1
Visible Text|50001,100,52
Text Message|50001,100,63
Help Message|50002,100,11
My Text|50002,100,43
您所期望的是:
$ cat Data3 | tr '/' ',' | sort -k3,3n -t',' | LC_NUMERIC=C sort -k2,2n -t'|' -s
Help Text|50001,100,7
My Message|50001,100,7
Visible Text|50001,100,52
Text Message|50001,100,63
Invisible Text|50002,100,1
Help Message|50002,100,11
My Text|50002,100,43
只要没有其他'|'
,以下代码对我'|'
文字中的字符。
tr '|' '/' | sort -n -t '/' -k3 -k4 | sed -re 's/^([^/]*)\\/(.*)$/\\1|\\2/'
awk
一个小技巧
$ cat Data3 | awk -F'[|/]' '{print $2"\t"$4"\t"$0}' | sort -k1 -k2 -n | cut -f3-
Help Text|50001/100/7
My Message|50001/100/7
Visible Text|50001/100/52
Text Message|50001/100/63
Invisible Text|50002/100/1
Help Message|50002/100/11
My Text|50002/100/43
-F'[|/]'
指定了所有分隔符-F'[|/]'
使用awk
,先打印排序键$2"\\t"$4
,然后打印输入行$0
-k1 -k2
进行一种sort
(注意:与-k1,2
) cut
回输入线 在许多情况下通用
您可以使用以下(无效但简单)的脚本:
#!/usr/bin/perl
print sort { @ka = split ?[|/]?, $a;
@kb = split ?[|/]?, $b;
$ka[1] <=> $kb[1]
|| $ka[3] <=> $kb[3]
|| $ka[0] cmp $kb[0]
} <>
您可以省略|| $ka[0] cmp $kb[0]
|| $ka[0] cmp $kb[0]
如果您不希望将具有相同值的行按文本消息排序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.