我们有一个固定宽度的文件
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循环但由于我们通过读取每条记录来执行此拆分,因此执行时间过长。
输出文件可以是逗号分隔或固定宽度。
答案 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