我有一个巨大的文本文件,其中数据按页分隔。例如,文本采用以下格式,我想按页读取行并将每个页面存储在单独的文件中。
Page 1
line 1
line 2
line 3
line 4
line 5
Page 2
line 1
line 2
line 3
line 4
line 5
Page 3
line 1
line 2
line 3
line 4
line 5
答案1
解决方案:
awk '/^Page [0-9]+$/ {N = $2}; {print > "page"N}' pages
测试运行:
==> page1 <==
line 1
line 2
line 3
line 4
line 5
==> page2 <==
line 1
line 2
line 3
line 4
line 5
==> page3 <==
line 1
line 2
line 3
line 4
line 5
但是,如果有数千个页面,则在某些awk
实现中,您可能会遇到打开文件数量的限制。您可以通过在找到新页眉时关闭上一页的文件来解决这个问题。您可能还需要用 0 填充文件名中的数字,以便ls
按升序显示它们:
awk '
/^Page [0-9]+$/ {close(file); file = sprintf("page%04d", $2)}
{print > file}' pages
假设输入每页仅包含一次 。Page n
答案2
另一种解决方案,它不像原来的解决方案那么优雅awk
,因为它需要:
- 知道每页的行数
这个数字必须在所有页面上保持不变
split -l 6 -a 2 -d input page_
这里,6是每页的行数:1个标题行+5个数据行
答案3
使用csplit
:
$ csplit -s -f page- file '/^Page/' '{1}'
$ ls
file page-00 page-01 page-02
$ cat page-00
Page 2
line 1
line 2
line 3
line 4
line 5
$ cat page-01
Page 2
line 1
line 2
line 3
line 4
line 5
$ cat page-02
Page 3
line 1
line 2
line 3
line 4
line 5
该csplit
实用程序根据给定文件的最后一个参数分割给定文件。此处,/^Page/
and{1}
指示csplit
每次匹配时根据给定的正则表达式分割文件。对于 GNU csplit
,您可能希望使用{*}
而不是{1}
(上面的示例是为 OpenBSD 编写的csplit
)。
答案4
命令:
awk '$0 ~/Page 1/{f=1}$0 ~/Page 2/{f=0}f' o.txt > firstfile
awk '$0 ~/Page 2/{f=1}$0 ~/Page 3/{f=0}f' o.txt > secondfile
awk '/Page 3/,/,/{print $0}' o.txt >thirdfile
输出
een@praveen:~$ awk '$0 ~/Page 1/{f=1}$0 ~/Page 2/{f=0}f' o.txt > firstfile
Page 1
line 1
line 2
line 3
line 4
line 5
praveen@praveen:~$ awk '$0 ~/Page 2/{f=1}$0 ~/Page 3/{f=0}f' o.txt > secondfile
Page 2
line 1
line 2
line 3
line 4
line 5
awk '/Page 3/,/,/{print $0}' o.txt >thirdfile
Page 3
line 1
line 2
line 3
line 4
line 5
praveen@praveen:
〜$