使用不是换行符或零字节的记录定界符对 CSV 进行排序

Sorting CSV with record delimiter that is not a newline or zero byte

我的 CSV 看起来像这样:

"212314334","a sentence with new line in it \n
this is the next line","kajdfad","213",ENDOFLINE\r\n
"212314333","another sentence with new line in it \r\n
this is the next line","kawad","21453",ENDOFLINE\r\n

所以记录中间可能有换行符。文件中也可能有不可打印的字符。记录分隔符为,ENDOFLINE\r\n.

Linux sort 具有换行符或零字节的记录分隔符,因此我无法使用它。

我尝试使用 awkRS:

awk -F, 'BEGIN {RS="ENDOFLINE\r\n"} {print }' myFile | sort -t $',' -k 1

但看起来 sort 仍然使用换行符作为分隔符,因为它在中间拆分记录。

有什么解决办法吗?

使用同事建议的可能解决方案进行编辑:

awk -F, 'BEGIN {RS="END\r\n";i=0;} {array[i]=","[=12=]"END\r"; i=i+1}END {n = asort(array, dest);for (i=1; i<=n; i++) dest[i] = substr(dest[i], index(dest[i], )) ; for (i=1; i<=n; i++) print dest[i]}

这与我举的例子不完全一样。这里的排序是根据第二个feild来排序的,第二个feild作为第一个字段附加到排序中,然后被移除。

编辑:在评论中向我指出了原始代码中的一些令人尴尬的错误。这应该可以解决它们。

问题是 sort 不再知道 awk 所做的拆分,因为 awk 的输出与输入没有变化。我的建议是在 awk;

中完成所有操作
awk -F, 'BEGIN { RS = "ENDOFLINE\r\n" } { lines[] = lines[] [=10=] RT } END { n = asorti(lines, keys); for(i = 1; i <= n; ++i) { printf("%s", lines[keys[i]]) } }'

awk代码是

#!/usr/bin/awk -F, -f

BEGIN {
  RS = "ENDOFLINE\r\n"
}
{
  lines[] = lines[] [=11=] RT     # remember lines by first field in an associative
                                  # array; append lines with duplicate keys.
}
END {
  n = asorti(lines, keys)         # sort keys; sorted keys end up in the array
                                  # named keys with indices from 1 to n
  for(i = 1; i <= n; ++i) {       # then walk through the sorted keys
    printf("%s", lines[keys[i]])  # and print the lines.
  }
}

另一个 awk

awk -F, -vRS="ENDOFLINE/n" '
        {a[NR]=[=10=]}END{x=asort(a);while(++i<=x)printf "%xs",a[i] RT}' file

这与 wintermutes 的工作原理类似,但按内容而不是索引排序。

由于您对 $1 进行排序,并且它是从头开始排序的,因此对整行进行排序应该会得到相同的结果。

我假设所有第一个字段的长度都与问题中显示的一样。