如何阅读逗号分隔值

时间:2017-10-13 19:02:52

标签: unix awk

我们有一个固定宽度的文件

Col1 length 10
Col2 length 10
Col3 length 30
Col4 length 40

样本记录

ABC       123       xyz.                          5171-5261,51617
ABC.          1234.       Xxy.      81651-61761

Col4可以包含任意数量的逗号分隔值 长度为40个字符的1个或多个:
如果该记录的值为1,则输出文件没有变化。 如果有多个值,即以逗号分隔(5171-5261,51617) 输出文件应该有多个记录。

1 record 
ABC.  123.    Xyz.   5171-5261
ABC     123.   Xyz.   51617

最有效的方法是什么? 截至目前尝试使用while和for循环但由于我们通过读取每条记录来执行此拆分,因此执行时间过长。

输出文件可以是逗号分隔或固定宽度。

1 个答案:

答案 0 :(得分:1)

awk是你的朋友。

单行awk将实现您的需求:

awk -v FIELDWIDTHS="10 10 30 40" '{ if (match($4,",")) { split($4,array,","); for (i in array) { print $1,$2,$3,array[i]; }; } else { print $1,$2,$3,$4 }; }' samp.dat 

为便于阅读,代码为:

{
    if (match($4,",")) {
        split($4,array,",");
        for (i in array) {
            print $1,$2,$3,array[i];
        };
    } else {
        print $1,$2,$3,$4 
    };
}

使用您提供的样本数据进行测试得出:

ABC        123        xyz.                           5171-5261
ABC        123        xyz.                           51617
ABC.           1234.        Xxy.      81651-61761 


工作原理:
awk一次读取一行文件。
FIELDWIDTHS指令允许我们将每列引用为$1,$2...
现在我们有了我们的列,我们可以在match($4,",")的第四个字段中查找逗号 如果我们找到一个,我们在第四个字段中创建一个由逗号分隔split($4,array,",")的值的数组 然后我们遍历这个数组并打印多行输出,一行用于数组的每个元素 如果第四个字段没有逗号,则else子句打印一行 对于固定宽度文件中的每一行重复此过程。

注意: awk associative arrays不保证保留数据的顺序。 这意味着您的输出可能会显示为

ABC        123        xyz.                           51617
ABC        123        xyz.                           5171-5261
ABC.           1234.        Xxy.      81651-61761

即。输入数据中的5171-5261,51617从第一个值之前的第二个值生成一行。

如果排序对您很重要,那么您可以使用下面的代码首先从输入数据生成csv,然后生成保留订单的输出。

awk -v FIELDWIDTHS="10 10 30 40" '{print $1,$2,$3,$4}' OFS=','  samp.data > samp.csv
awk -F',' '{ for (i=4; i<=NF; i++) { print $1,$2,$3,$i } }' samp.csv