【问题标题】:splittling a file into multiple with a delimiter awk使用分隔符 awk 将文件拆分为多个
【发布时间】:2016-08-01 00:40:53
【问题描述】:

我正在尝试将文件均匀地拆分为多个块。这是我的代码:

awk '/*/ { delim++ } { file = sprintf("splits/audio%s.txt", int(delim /2)); print >> file; }' < input_file

我的文件如下所示:

"*/audio1.lab"
0 6200000 a
6200000 7600000 b
7600000 8200000 c
.
"*/audio2.lab"
0 6300000 a
6300000 8300000 w
8300000 8600000 e
8600000 10600000 d
.

它给了我一个错误:awk: line 1: syntax error at or near * 我对 awk 了解得不够多,无法理解这个错误。我尝试转义字符,但仍然无法弄清楚。我可以在 python 中编写脚本,但我想学习如何在 awk 中执行此操作。任何awkers知道我做错了什么?

编辑:我有 14021 个文件。我以前两个为例。

【问题讨论】:

  • 尚不清楚您到底想做什么。您是否尝试拆分文件或合并文件或其他内容?该样本是输入一个文件还是两个单独的文件?阐明I am trying to split files evenly in a number of chunks. 的含义并根据该示例输入发布预期输出。
  • 按标题分割文件。方便地,标题是唯一带有“*”的行
  • 所以你有 1 个文件看起来像你发布的输入,你想把它分成多个文件,每个块一个?或者您是否尝试将输入文件中的 2 个块放入每个输出文件(因此除以 2)或其他内容?这与您拥有 14021 个文件有什么关系?您想要跨所有输入文件的每个块的唯一输出文件还是某种合并或什么?同样,更好的描述和发布预期的输出将是一个很大的帮助。
  • 每块一个。我进行了编辑,因为 David Gish 的第一个响应适用于较小的文件,而他的编辑适用于较大的文件。

标签: file awk split


【解决方案1】:

一方面,你的正则表达式是非法的; '*' 表示匹配前一个字符 0 次或多次,但没有前一个字符。

不完全清楚您要做什么,但是当您遇到带有星号的行时,您想增加文件号。要匹配星号,您需要对其进行转义:

awk '/\*/ { close(file); delim++ } { file = sprintf("splits/audio%d.txt", int(delim /2)); print >> file; }' < input_file

还要注意%dint 十进制输出的正确格式字符。

【讨论】:

  • 你是对的,大卫。当我找到一个星号时,我正试图提高。我也按照您的建议进行了尝试,但是它给了我一个不同的错误: awk: cannot open "splits/audio1021.txt" for output (打开的文件太多) 我有两个以上的文件,我试图让问题保持简单。这是内存问题吗?
  • 文件很多。在您的第一个子句中,尝试类似: {close (file);分隔符++}
  • 完美!你先生是个巫师!我不知道关闭。这真是个好东西。
  • 很高兴为您提供帮助
  • 不要为每个输入行重新计算file,只需在增加delim 时计算一次。你的意思不是&gt;&gt;,你的意思是&gt;(这是awk,不是shell)。不要将输入重定向与 awk 一起使用,因为它不能扩展到多个文件,并且会剥夺 awk 使用 FILENAME 的能力。
【解决方案2】:

了解这个问题的所有其他内容是关于什么的,但只需将输入文件拆分为单独的输出文件,您所需要的只是:

awk '/\*/{close(out); out="splits/audio"++c".txt"} {print > out}' file

由于像*?+ 这样的“重复”元字符在作为正则表达式中的第一个字符时可以具有字面意义,因此正则表达式/*/ 在某些情况下可以正常工作(例如gawk ) 但不是所有的 awks,而且由于您显然在打开太多文件时遇到问题,因此您不能使用 gawk(它为您管理文件),因此您可能需要转义 *close() 每个输出文件时'写完了。这样做没有坏处,它使脚本可移植到所有 awks。

【讨论】:

  • 干净多了。我考虑过重写,但指出损坏的地方似乎更有指导意义。
  • 还有一个边缘情况(干净代码的长期祸根),第一个 * 之前的任何内容都会丢失。为了解决这个问题,out 应该在 BEGIN 部分中初始化。
  • OP 在第一个 * 之前没有任何行,因此我们不需要处理这种潜在情况。如果该语句是错误的,那么 OP 需要修复他的示例输入/输出,以便我们可以看到我们真正在处理什么。
  • 确实如此,只是指出除非我们立即遇到星号,否则我们将输出为 nil 文件名。我不确定各种 awk 对此有多么挑剔,但松散的结局困扰着我。
  • awk 会立即产生致命错误,即在输出重定向右侧有一个空字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-24
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多