我有一个管道分隔的文件,其格式如下
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