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

3ks*_*stc 5 csv sorting bash 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
Run Code Online (Sandbox Code Playgroud)

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

附录:

因此,我使用以下代码将十六进制字符串转换为十进制字符串:

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
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*eed 5

如果字符串都具有相同的位数和相同的字母大小写(如示例数据中所示),则可以按原样排序。默认词法排序会将它们按正确的顺序排列,因为十六进制数字 0-9a-f 在标准字符集中按该顺序出现。

\n

如果您可能有一些数字位数不同的数字,或者字母数字混合了大小写,那么最好的选择可能是转换为十进制,按数字排序,然后转换回来。如果您有 GNU 版本的 awk,则可以使用它来进行转换:

\n
awk -v{,O}FS=, '{$1=strtonum("0x"$1)}1' $filename | \n    sort -t, -n -k1,1 |\n    awk -v{,O}FS=, '{$1=sprintf("%x",$1)}1' >$new_filename\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
570e2e5c,1460539517,SOM3-String-123,08-5a-0c-59\n570e2e5e,1460539518,SOM3-String-123,08-00-0c-59\n570e2e60,1460539519,SOM3-String-123,09-00-68-22\n570e2e81,1460539520,SOM3-String-123,08-00-0c-59\n570e2e87,1460539521,SOM3-String-123,09-5e-6b-22\n570e2e90,1460539522,SOM3-String-123,08-00-0c-59\n570e2e95,1460539523,SOM3-String-123,09-00-67-22\n
Run Code Online (Sandbox Code Playgroud)\n

解释:

\n

-v name=value告诉awk设置一个将存在于程序上下文中的变量;这是一种注入值的便捷方法,而无需处理代码中字符串插值所带来的引用复杂性。但有些变量名比较特殊;FS告诉它awk使用什么(F)字段(S)分隔符将输入行拆分为字段,并OFS告诉它在打印行时使用什么(O)输出字段分隔符。该-v{,O}FS=,序列只是将两个变量设置为相同值的快捷方式;它通过 shell 的大括号扩展而扩展为-vFS=, -vOFS=,. 因此,在 awk 程序中,每一行都将用逗号预先分割为字段,各个字段值位于变量$1$2等中。当这些变量发生更改时,打印回来时它们将用逗号重新连接在一起。

\n

awk传递给选项之后的字符串中的代码-vawk要运行的程序。这样的程序是一系列(条件,块)对;根据每行输入检查每个条件,然后如果条件为真则评估该块。如果一个块出现时没有条件,则它会在每一行上运行;如果一个条件没有块出现,它会导致当前行 \xe2\x80\x93 或由 OFS 连接的当前行的字段(如果其他块已进行修改 \xe2\x80\x93 )被打印出来。

\n

上面的程序使用两个默认值;每个都以没有条件的代码块开始,因此它在每一行上运行,并以没有代码块的条件结束:1,它始终为真,因此在代码块执行完毕后,每一行都会打印出来它的变化。

\n

第一个awk程序使用该strtonum函数将第一个字段转换为十进制。这就是为什么这个解决方案只能在 GNU awk 中工作;BSD awk(也是 macOS 上附带的)没有strtonum. 我们必须在字段值前面添加“0x”,以便知道将strtonum其视为十六进制,但一旦它是数值,它将以十进制打印出来。因此,awk除了第一个字段转换为十进制之外,输出与输入相同。

\n

我们将其提供给sort,告诉它-n按第一个 ( -k1,1) 逗号分隔 ( -t,) 字段进行数字排序 ( ),然后将排序后的输出提供给第二个awk,后者使用该sprintf函数将第一个数字字段转换回十六进制。

\n