我们正在解析一些不包含 CR/LF 的大型 EDI 文件。但是,它们确实包含~
(波浪号) 作为段分隔符。
我正在尝试提取该文件的控制记录,我的 120 MB 文件的最后几个字节如下所示:
~REF*1L*0711882~SE*62300*39093~GE*1*500001242~IEA*1*500001241~
文件中只有一个控制记录并且它总是以 开头~SE
。
那么,有没有一种使用标准 Unix 的简单方法切,awk,grep等工具来剪切此文件以获取 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 之类的情况东南foobarquz~东南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()
使用管道!