如何使用十六进制数对CSV文件进行排序?

时间:2016-04-15 00:06:35

标签: bash sorting csv hex

我有一个金发碧眼的时刻,似乎无法理解它,但我有一个csv文件(下面的示例),其中我想按第一个值排序行在行中 - 六 - 数字(从小到大)

570e2e5c,1460539517,SOM3-String-123,08-5a-0c-59
570e2e81,1460539520,SOM3-String-123,08-00-0c-59
570e2e87,1460539521,SOM3-String-123,09-5e-6b-22
570e2e5e,1460539518,SOM3-String-123,08-00-0c-59
570e2e90,1460539522,SOM3-String-123,08-00-0c-59
570e2e95,1460539523,SOM3-String-123,09-00-67-22
570e2e60,1460539519,SOM3-String-123,09-00-68-22

问:如何用BASH脚本按行十六进制的第一行元素排序csv文件行?

附录:

所以我使用以下代码将十六进制字符串转换为dec字符串:

IFS=','
while read f1 f2 f3 f4 
do 

f1_upper_case=`echo "$f1" | tr '[:lower:]' '[:upper:]'`
f1_dec=$((16#$f1_upper_case))
echo "$f1_dec,$f2,$f3,$f4" >>$csv_temp 

done < $csv

我将尝试在csv文件中按$f1_dec排序。

2 个答案:

答案 0 :(得分:2)

如果字符串都具有相同的数字位数,则可以按词法排序。如果您可能有一些不同的大小数字,那么您最好的选择可能是转换为十进制,数字排序,然后转换回来:

awk -F, -vOFS=, '{$1=strtonum("0x"$1)}1' $filename | sort -t, -n -k1,1 |
awk -F, -vOFS=, '{$1=sprintf("%x",$1)}1' >$new_filename

运行您的示例输入,我得到此输出:

570e2e5c,1460539517,SOM3-String-123,08-5a-0c-59
570e2e5e,1460539518,SOM3-String-123,08-00-0c-59
570e2e60,1460539519,SOM3-String-123,09-00-68-22
570e2e81,1460539520,SOM3-String-123,08-00-0c-59
570e2e87,1460539521,SOM3-String-123,09-5e-6b-22
570e2e90,1460539522,SOM3-String-123,08-00-0c-59
570e2e95,1460539523,SOM3-String-123,09-00-67-22

说明:

-F,告诉awk在逗号的(F)字段分隔符上拆分输入行。 -vOFS=,告诉它使用逗号作为(O)utput(F)ield(S)eparator - 也就是说,当它将行打印出来时,将逗号保留为分隔符。

字符串中的代码每行输入运行一次,字段分为变量$1$2等。{内的块... {首先运行{1}}并更改}的值;之后的$1会导致新的1字段打印出来。

$1函数将字符串转换为数字,遵守C字面约定,前导0表示基数为8,前导0x表示基数为16.所以通过将strtonum添加到"0x" ,我们得到一个它将识别为十六进制的字符串。我们在$1中返回并存储的号码将在打印出来时自动转换为小数。

因此,第一个$1命令的最终结果是将第一列转换为十进制。然后我们可以awk。我们再次使用逗号作为字段分隔符 - 对于sort,我们使用sort表示。我们希望以数字方式排序(-t),并且我们希望排序键(-n)仅包含第一个字段(-k)。

然后我们要转换回十六进制。第二个1,1与第一个awk大致相同,但我们称之为strtonum,而不是sprintf。这是一个从其他值构建字符串的函数,"%x"格式说明符表示取一个数字并将其转换为十六进制字符串。

答案 1 :(得分:0)

输入:

$ cat /tmp/so36636125.txt 
570e2e5c,1460539517,SOM3-String-123,08-5a-0c-59
570e2e81,1460539520,SOM3-String-123,08-00-0c-59
570e2e87,1460539521,SOM3-String-123,09-5e-6b-22
570e2e5e,1460539518,SOM3-String-123,08-00-0c-59
570e2e90,1460539522,SOM3-String-123,08-00-0c-59
570e2e95,1460539523,SOM3-String-123,09-00-67-22
570e2e60,1460539519,SOM3-String-123,09-00-68-22

转换一个班轮:

$ awk '{ dec = sprintf("%d", "0x" $1); print dec " "  $0 }' /tmp/so36636125.txt | sort -n -k 1 | cut -f2- -d' '
570e2e5c,1460539517,SOM3-String-123,08-5a-0c-59
570e2e5e,1460539518,SOM3-String-123,08-00-0c-59
570e2e60,1460539519,SOM3-String-123,09-00-68-22
570e2e81,1460539520,SOM3-String-123,08-00-0c-59
570e2e87,1460539521,SOM3-String-123,09-5e-6b-22
570e2e90,1460539522,SOM3-String-123,08-00-0c-59
570e2e95,1460539523,SOM3-String-123,09-00-67-22

$ awk --version
GNU Awk 3.1.7

说明:

  • awk添加一个新的第一列作为。的十进制表示 十六进制数
  • sort数字化第一栏
  • cut删除第一个 柱