记录转到 PIPE 分隔文件中的下一行

记录转到 PIPE 分隔文件中的下一行

我有一个管道分隔的文件,其格式如下

1|ABC|11|DEF|111
2|ABC|22|PQR
ST
UW|222
3|ABC|33|XYZ|333
4|ABC|44|LMN|444

2现在,对于从当我尝试将此记录插入表中开始的行,仅插入记录直到PQR并开始从开始的行插入记录4

如果有任何命令将所有第 2 行记录放入单行中,这将帮助我成功将第 2 行插入表中,我将不胜感激?

答案1

使用 GNU 将记录中嵌入的换行符替换为空格awk

num_fields=4
awk -v RS='([^|]*\\|){'"$num_fields"'}[^|]*\n' '
  {
   n = split(RT, a,"|"); 
   for (i=1; i<=n; ++i)
   {
      gsub("\n", " ", a[i]); 
      printf "%s%s", a[i], i==n?"\n":"|"
   }
  }' file

这给出了

1|ABC|11|DEF|111 
2|ABC|22|PQR ST UW|222 
3|ABC|33|XYZ|333 
4|ABC|44|LMN|444 

这里的技巧是使用 GNUawk对任意记录分隔符的支持将一个定义为四个管道终止字段,后跟一个换行符终止字段,不允许任何字段包含嵌入管道(通过RS='([^|]*\\|){4}[^|]*\n')。

然后可以通过 访问符合此规范的实际记录分隔符RT。这是一个简单的问题,RT通过管道将其拆分为数组a,从每个元素中剥离嵌入的换行符a,最后通过重新连接元素来重建记录a

答案2

从这种疯狂的文件格式中提取片段的一种方法是使用 Perl。

#!/usr/bin/perl
#
use warnings;
use strict;

undef $/;
my $file = <>;

while ($file =~ /^(.*?\|.*?\|.*?\|.*?\|.*?)$/mscg) {
    my $fields = $1;
    $fields =~ s/\n(.)/\\n$1/sg;
    print "$fields\n";
}

该代码将整个文件放入内存中,然后将其重新块到|每行五个分隔字段上。嵌入的换行符替换为\n.

如果调用该脚本,repipe.pl您可以使用它来处理datafile名为perl repipe.pl datafile.

如果您感到有挑战性,您可以将其嵌入为这样的单行代码,但它对可维护性没有多大作用:

perl -e 'undef $/; $file = <>; while ($file =~ /^(.*?\|.*?\|.*?\|.*?\|.*?)$/mscg) { $fields = $1; $fields =~ s/\n(.)/\\n$1/sg; print "$fields\n"; }' datafile

这是示例数据文件的输出结果

1|ABC|11|DEF|111
2|ABC|22|PQR\nST\nUW|222
3|ABC|33|XYZ|333
4|ABC|44|LMN|444

相关内容