如何从文件中间提取字节?

如何从文件中间提取字节?

我们正在解析一些不包含 CR/LF 的大型 EDI 文件。但是,它们确实包含~(波浪号) 作为段分隔符。

我正在尝试提取该文件的控制记录,我的 120 MB 文件的最后几个字节如下所示:

~REF*1L*0711882~SE*62300*39093~GE*1*500001242~IEA*1*500001241~

文件中只有一个控制记录并且它总是以 开头~SE

那么,有没有一种使用标准 Unix 的简单方法awkgrep等工具来剪切此文件以获取 SE*62300*39093 段,除了将其转换~为 CRLF 并尾随文件的最后三行之外?

免责声明:
我不是 Unix 专家,所以答案对于经验丰富的用户来说可能是显而易见的。而且,我无法控制文件格式。

答案1

您可以使用以下方式执行此操作:
tr "~" "\n" < edi_file | tail -20 | grep ^SE

该 trtr将所有波浪号转换为换行符。(以 \n 表示)。

然后将其输出送至尾部,尾部将丢弃除最后 20 行之外的所有内容。

您可以根据要搜索的内容对此进行微调。如果没有它,整个文件都会被输入到 grep,这可能比 tail 占用更多的资源。如果您有特定版本的 tail,它支持基于字节而不是行显示文件的一部分,您甚至可以更快地使用这一步。

我没有选择该选项,因为你的帖子被标记为通用unix而不是具有最新 GNU 工具和 GNU 特定扩展的现代 Linux

最后grep将最后的行过滤为包含 SE 的行,并且插入符号 ( ^) 确保它位于行首。(防止出现 ~foooo 之类的情况东南foob​​arquz~东南wewantthispartonly~boobar~用于显示两行)。

答案2

虽然我明白你不想修改原始文件,但你可以在管道中进行转换。这样,你就不会修改数据,但你仍然可以获得转换~为行尾的好处(以 Unix 实用程序术语而言)。

这应该可以解决问题:

cat ding | tr "~" "\n" | tail -3

它不是宇宙中最有效的东西,但即使运行 120 MB 的文件也不是什么大问题。

请注意,这两组引号不是可选的 -如果删除引号,~则两者\n都会被 shell 解释。

答案3

首先,这对于大文件来说效率很低tr,因为您实际上想要的是末尾的数据,并且tr会处理将被丢弃的数据。

用来tac反向读取文件,然后取前 20 行(反向的,所以实际上是最后一行),再次反向以获取原始顺序,现在grep

tac -s~ edi_file | head -n 20 | tac | grep ^SE

请记住你不能seek()使用管道!

相关内容