2017-10-13 161 views
0

我们有一个固定的宽度文件如何读取逗号分隔值

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

样品记录

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

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

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

什么是最有效的方法来做到这一点。 截至目前试图使用while和for循环,但它需要很长时间才能执行,因为我们通过读取每条记录来进行分割。

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

+0

一个很好的问题会包含一小组样本数据,该输入的预期输出,当前代码/输出/错误消息以及您为什么不工作的想法。请阅读https://stackoverflow.com/help/on-topic,http://stackoverflow.com/help/how-to-ask,http://stackoverflow.com/help/dont-ask,http:// stackoverflow.com/help/mcve,也许是http://stackoverflow.com/tour。祝你好运。 – shellter

回答

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关联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 
+1

而且我知道如何花费大量的时间回答问题并获得反馈,令人沮丧;-)。很好的答案。继续发帖。 – shellter