【问题标题】:How to Split a Delimited Text file in Linux, based on no of records, which has end-of-record separator in data fields如何在 Linux 中根据记录数拆分分隔文本文件,该文件在数据字段中具有记录结束分隔符
【发布时间】:2017-06-19 13:26:14
【问题描述】:

问题陈述:

我有一个从 Teradata 卸载的分隔文本文件,该文件恰好在数据字段中包含“\n”(换行符或 EOL 标记)。

同一 EOL 标记位于整行或整条记录的每一新行的末尾。

我需要将此文件拆分为两个或多个文件(基于我提供的记录数),同时在数据字段中保留换行符,但在每行末尾保留换行符。

例子:

1|Alan
Wake|15
2|Nathan
Drake|10
3|Gordon
Freeman|11

期待:

file1.txt

1|Alan
Wake|15
2|Nathan
Drake|10  

file2.txt

3|Gordon
Freeman|11 

我尝试过的:

 awk 'BEGIN{RS="\n"}NR%2==1{x="SplitF"++i;}{print > x}' inputfile.txt

代码无法区分数据字段换行符和实际换行符。有没有办法实现?

编辑:: 我已经用示例更改了问题陈述。请分享您对新示例的看法。

【问题讨论】:

  • 详细说明based on no of records given by me
  • 观看这部分 "NR%2==..." 表示每两条记录我拆分
  • 您将不得不告诉我们将 X 行放在一个文件中并将 Y 行放在另一个文件中的标准是什么。有很多替代方案可以产生该输出(每 4 行拆分,大致分成两半,同时保留成对的行等) - 告诉我们您真正想要哪一个。

标签: linux shell unix awk


【解决方案1】:

使用以下 awk 方法:

awk '{ r=(r!="")?r RS $0 : $0; if(NR%4==0){ print r > "file"++i".txt"; r="" } }
       END{ if(r) print r > "file"++i".txt" }' inputfile.txt
  • NR%4==0 - 您的 logical 单行占用了两个 physical 记录,因此我们希望在每 4 条记录上分开

结果

> cat file1.txt 
1|Alan
Wake
2|Nathan
Drake

> cat file2.txt 
3|Gordon
Freeman

【讨论】:

  • 感谢您的解决方案,但让我明白这一点,“如果(NR%4==0)”在这个表达式中没有“4”来自逻辑:“字段数在创纪录的 X 次拆分中”?因为这里每条记录有两列,我想要两个拆分文件......所以有效的模数将与“4”一起应用?
  • 在这种情况下,如果我想将这个文件分成 3 份并且每条记录有 3 个字段,会发生什么情况。由于模 9 1|Alan"\n" Wake|15"\n" 2|Nathan"\n" Drake|10"\n" 3|Gordon"\n" Freeman|11",awk 以错误的方式拆分它\n" 4|Suman"\n" Gupta|33"\n" 5|Indranil"\n" Roy|34"\n" with awk '{ r=(r!="")?r RS $0 : $0 ; if(NR%9==0){ print r > "file"++i".txt"; r="" } } END{ if(r) print r > "file"++i".txt" }' SplilineIN2.csv
  • @SumanGupta,你写了 每条记录有 3 个字段 - 如果我们谈论字段,那么应该有字段分隔符。你的情况是什么领域?
  • 它的“|”在这种情况下,我修改了我的 OP 中的示例
  • @SumanGupta,用您的新输入扩展您的问题并发布最终预期输出(在格式化视图中)
【解决方案2】:

如果您使用的是 GNU awk,您可以通过适当地设置 RS 来做到这一点,例如:

parse.awk

BEGIN { RS="[0-9]\\|" }

# Skip the empty first record by checking NF (Note: this will also skip
# any empty records later in the input)
NF {
  # Send record with the appropriate key to a numbered file
  printf("%s", d $0) > "file" i ".txt"
}

# When we found enough records, close current file and 
# prepare i for opening the next one
#
# Note: NR-1 because of the empty first record
(NR-1)%n == 0 { 
  close("file" i ".txt")
  i++
}

# Remember the record key in d, again, 
# becuase of the empty first record
{ d=RT }

像这样运行它:

gawk -f parse.awk n=2 infile

其中n 是要放入每个文件的记录数。

输出:

file1.txt

1|Alan
Wake|15
2|Nathan
Drake|10

file2.txt

3|Gordon
Freeman|11

【讨论】:

  • 对不起,它没有帮助:(我相信我的解释不足以描述我的实际期望。我已经用一个新的例子相应地改变了问题陈述。
  • 最后一行的 RT 是什么意思?
  • 干杯@EdMorton。我真的需要开始阅读变更日志。完全错过了=}
  • @Thor...“强大”谢谢!像魅力一样工作!你就是男人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 2016-10-05
相关资源
最近更新 更多