shell脚本排序

shell脚本排序

我正在尝试对一个小文件进行排序,其中一些条目包含两个单词,但我想将其作为一个条目进行排序。

例如考虑这个小清单

 peter barker painter
 carl baker cook
 joshua carpenter

这些都是名字和职业。现在说我想使用排序来对这些条目进行排序。

问题是 sort 使用空格作为字段,所以如果我 sort -k 1n 我会按名字排序

但我想按全名排序,然后也可以选择按职业排序。正如您所看到的,有些整体没有全名,约书亚只有他的名字和职业。因此,对于他来说,我只想按名字排序,但按其他人的全名排序。

这能实现吗?

答案1

假设只是缺少姓氏(而不是名字)并且文件中的单词不包含空格(这将使其极其困难),首先将数据转换为制表符分隔格式,并将缺少的姓氏替换为空字段:

$ awk -v OFS='\t' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file
peter   barker  painter
carl    baker   cook
joshua          carpenter

awk脚本将检测包含两个或三个字段的行。它只是将已经具有三个字段的行重新格式化为三个制表符分隔的字段,同时将最初仅包含两个字段的行的第二个字段移动到第三个字段。

然后使用制表符作为分隔符对数据进行排序:

$ awk -v OFS='\t' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t $'\t' -k1,2 -k3
carl    baker   cook
joshua          carpenter
peter   barker  painter

此处进行的排序是按全名(字段一和字段二)进行排序,然后按职业进行排序。假设您使用的是类似于bash制表$'\t'符的 shell。


您可以使用不干扰数据的任何其他字符来代替制表符(此处:):

$ awk -v OFS=':' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t ':' -k1,2 -k3
carl:baker:cook
joshua::carpenter
peter:barker:painter

然后通过传递结果来替换所选的分隔符tr(这里用制表符替换,因为它看起来不错):

$ awk -v OFS=':' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t ':' -k1,2 -k3 | tr ':' '\t'
carl    baker   cook
joshua          carpenter
peter   barker  painter

相关内容