文件的单个记录被拆分为多行

文件的单个记录被拆分为多行

我们使用平面文本文件从 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.

此逻辑可能有必要了解需要删除换行符的特定字段的数据类型,以便它可以专门处理日期等。

相关内容