我们使用平面文本文件从 Informatica 转换后存储在 Teradata 表中。该文件包含 14 个字段(~ 分隔)。但由于记录分散在多条线上,informatica 无法将其拾取。
有什么方法可以通过使用 sed/awk 或任何其他命令来计算分隔符来连接记录吗?
样本记录---
48602040112~4100010080701242015~2010-01-21 10:23:44~Foods~7~Poultry ~Perdue Smart Chicken~Circular~06
-JAN-10~24-JAN-10~$5.99~24 oz., select varieties
up to 4 at this price, additional
Save up to $4.00
load up on savings~~1598
理想情况下应该是这样的——
48602040112~4100010080701242015~2010-01-21 10:23:44~Foods~7~Poultry ~ Perdue Smart Chicken~Circular~06-JAN-10~24-JAN-10~$5.99~24 oz., select varieties up to 4 at this price, additional Save up to $4.00 load up on savings~~1598
如果不明显,则它包含换行符。
答案1
tr -d \\n <infile | tr \~ \\n | paste -d~ - - - - - - - - - - - - - -
那可行。
答案2
您可以尝试使用sed
:
sed -rn ':a;/^([^~]*~){13}[^~]*$/!{N;s/\n//;ba};p' yourfile.tsv
它能做什么
该脚本由三个部分组成,并用 分隔;
:
:a
定义一个我们可以分支到的标签/^([^~]*~){13}[^~]*$/!{N;s/\n//;ba}
搜索完整的列/^([^~]*~){13}[^~]*$/
查找恰好包含 14 个字段(出现 0 次或多次非 的任何内容~
)的行,并以 13 次出现分隔~
。!
反转搜索结果(如果没有找到,则...){N;s/\n//;ba}
如果列不完整则执行的块N
读入另一行s/\n//
删除两行之间的换行符ba
分支 (b) 到我们之前定义的标签 (a)
p
打印完整的列
答案3
目前尚不清楚如何决定是加入带空格还是不带空格的分割字段。06<NL>-JAN-10
需要删除换行符,而varieties<NL>up to
需要将其替换为空格。
忽略上述问题,我们可以得到这个 Awk 命令原型:
$ awk 'BEGIN { RS = "~" }
{ gsub(/\n/,"",$0);
printf("%s", $0);
if (++i < 14) { printf("~"); }
else { i = 0; printf("\n"); } }' < in.txt > out.txt
我们使用 awk 来分割记录,~
以便每个字段实际上都是一条记录。然后只需使用 删除每条记录中的空白gsub
,如果字段是 1 到 13,则打印它,后跟分隔符;如果是 14,则后跟换行符(并重置计数)。
如果字段数不能被 14 整除,您将在输出中得到不完整的最后一行,并以换行符~
而不是换行符终止。
处理连接问题的一种可能方法是将换行符保留在原处,或者可能用数据中未出现的某些字符替换它们。将连接作为后处理步骤进行。假设@
数据中没有出现这种情况。如果我们用 替换换行符@
,那么我们可以使用常用的文本处理工具应用一些简单的模式替换。例如,按照s/([0-9])@-/\1-/
处理损坏日期的方式进行替换,例如06@-JAN
.
此逻辑可能有必要了解需要删除换行符的特定字段的数据类型,以便它可以专门处理日期等。