【问题标题】:Splitting text files on two consecutive lines containing only one integer number在仅包含一个整数的两个连续行上拆分文本文件
【发布时间】:2014-11-11 10:30:42
【问题描述】:

我有一个包含 os 3D 坐标列表的长文本文件。文件的开头由这样的标题组成:

10112
2455
121.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
121.417670 172.321300 1.704072 1

之后开始坐标列表。所有的行都由 3 到 7 个数字组成。例如:

0.001686 0.812066 -1.686245 0.074434
0.001695 0.816359 -1.692300 0.087190
0.001699 0.818673 -1.694508 0.097398
...

列表的总长度等于表头前两个数字的乘积(10112*2455)。这些是 PTX 文件,其中包含来自激光扫描的文本格式的 3D 点。

关键是文件是标题和坐标的串联,我想拆分文件在标题上打破它。理想的解决方案是将文件拆分为两个连续的单个整数行。我正在寻找一个通用的解决方案,例如使用 csplit,但 csplit 一次读取一行,因此它无法检测到两个连续的行。

作为最后的手段,我会自己编写一个软件,但如果有的话,我更愿意找到基于 CLI 工具(Awk?)的解决方案。

有什么想法吗?

谢谢

编辑:示例

假设我有一个包含以下内容的文件:

2
3
121.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
121.417670 172.321300 1.704072 1
6.001686 0.812066 -1.686245 0.074434
3.001695 0.816359 -1.692300 0.087190
6.001699 0.818673 -1.694508 0.097398
2.001686 0.812066 -1.686245 0.074434
1.001695 0.816359 -1.692300 0.087190
0.001699 0.818673 -1.694508 0.097398
3                                         <--- cut before this line
1
421.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
421.417670 172.321300 1.704072 1
1.001686 0.812066 -1.686245 0.074434
2.001695 0.816359 -1.692300 0.087190
3.001699 0.818673 -1.694508 0.097398

在这种情况下,我应该得到两个文件,在由单个整数组成的两行中的第一行之前剪切。

作为替代方案,知道这两个单数行表示组成部分的点数,我们可以说第一个输出文件由前 2*3+10=16(10 行标题和 6 data) 行,第二个文件由随后的 3*1+10=13 行组成(标题总是 10 行,这次是 3 行数据)。

【问题讨论】:

  • 你的意思是同一个文件里面有很多头,你要根据这个来打断?
  • 没错。我只需要在每次出现类似于标题的内容之前拆分原始文件,该标题以两行开头,每行由 i 个单个整数组成。

标签: text awk split csplit


【解决方案1】:

所以你想把一个文件分成不同的文件,在所有文件中打印标题。

这可以做到,你只需要指定要存储在参数-v lines=XX中的行数和要存储的标题行数-v head=YY

awk -v lines=5 -v head=2
     'NR<=head{header[NR]=$1; next}
      !((NR-3)%lines) {file="output_"++count; for (i=1;i<=head;i++) print header[i] > file}
      {print > file}
     ' file

单线:

awk -v lines=5 -v head=2 'NR<=head{header[NR]=$1; next} !((NR-3)%lines) {file="output_"++count; for (i=1;i<=head;i++) print header[i] > file} {print > file}' file

对于您的特定示例输入,给出head=2lines=5,它会返回两个文件:

$ cat output_1
10112
2455
121.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
$ cat output_2
10112
2455
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
121.417670 172.321300 1.704072 1

如果您想要为找到的每个标题拆分文件,应该这样做:

awk '(!flag && NF==1) {header[1]=$1; flag=1; next} (flag && NF==1) {header[2]=$1; flag=0; file="output_"++count; printf "%d\n%d\n", header[1], header[2] > file; next} {print > file}' file

说明

  • (!flag &amp;&amp; NF==1) {header[1]=$1; flag=1; next} 如果没有设置标志,则假定它是标题的第一行并存储它。
  • ( flag &amp;&amp; NF==1) {header[2]=$1; flag=0; file="output_"++count; printf "%d\n%d\n", header[1], header[2] &gt; file; next} 如果设置了标志,则意味着我们已经捕获了标题的第一行并且我们在第二行。为此,请取消设置标志,将文件名生成为 output_ + number 并使用存储的标头进行填充。
  • {print &gt; file} 在其余情况下,将当前行打印到文件中。

给定您的示例文件,它返回 output_1output_2

$ cat output_1
2
3
121.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
121.417670 172.321300 1.704072 1
6.001686 0.812066 -1.686245 0.074434
3.001695 0.816359 -1.692300 0.087190
6.001699 0.818673 -1.694508 0.097398
2.001686 0.812066 -1.686245 0.074434
1.001695 0.816359 -1.692300 0.087190
0.001699 0.818673 -1.694508 0.097398
$ cat output_2
3
1
421.417670 172.321300 1.704072
0.997697 0.067831 -0.000222
-0.067831 0.997697 0.000207
0.000236 -0.000191 1.000000
0.997697 0.067831 -0.000222 0
-0.067831 0.997697 0.000207 0
0.000236 -0.000191 1.000000 0
421.417670 172.321300 1.704072 1
1.001686 0.812066 -1.686245 0.074434
2.001695 0.816359 -1.692300 0.087190
3.001699 0.818673 -1.694508 0.097398

【讨论】:

  • 谢谢。但我需要保留原始文件的所有内容,只需将其拆分为不同的文件。原始文件需要在每个标题之前剪切。
  • @FedericoRusso 然后使用一些示例代表性输入和所需输出更新您的问题。现在不是很清楚你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多