管道的Ctrl + Z字符和EOF问题

时间:2015-12-30 19:23:53

标签: perl

我有一个由第三方提供的巨大文件,它似乎是在类似Windows / DOS的环境中生成的。该文件的最后一行包含^Z个字符。当我查看已处理的文件时,我注意到了这一点,最后一行包含^Z。我添加了一些逻辑从输入中跳过这一行,它工作正常,直到我改变我的代码以从stdin而不是文件获取输入。

以下是此问题的简单说明。当我对包含和不包含^Z的单个文件流进行行计数时,它会报告正确的值:

unzip -j -p -qq file1.zip | perl -nle 'print' | wc -l
3451
unzip -j -p -qq file2.zip | perl -nle 'print' | wc -l
3451

unzip -j -p -qq file1.zip | perl -nle 'next if /^\cZ/; print' | wc -l
3450
unzip -j -p -qq file2.zip | perl -nle 'next if /^\cZ/; print' | wc -l
3450

现在,当我尝试同时处理两个文件时,我丢失了一条记录。我猜这与^Z角色有关,但我无法弄清楚我能做些什么:

unzip -j -p -qq '*.zip' | perl -nle 'print' | wc -l
6901  ## this should have been 6902 

unzip -j -p -qq '*.zip' | perl -nle 'next if /^\cZ/; print' | wc -l
6899  ## this should have been 6900 

这些文件很大(每个20 + GB),它们要以3-6个文件的形式读取,所以我想避免逐个处理它们,然后再连接。有关如何避免^Z字符而不遇到上述问题的任何想法?

我在Linux机器上。顺便说一下,在vim中打开文件不显示最后一条记录(即^Z),而设置set ff=unix也没有改变这一点。因此,vim报告单个解压缩文件的3450行,并为合并的解压缩文件报告6900

谢谢!

1 个答案:

答案 0 :(得分:4)

由于^Z后面没有行结尾,unzip正在生成

 file1:1
 file1:2
 file1:3
 ^Zfile2:1
 file2:2
 file2:3
 ^Z

所以你删除了第二个文件的第一行。您只需删除^Z而不是整行。

perl -pe's/^\cZ//'

那就是说,unzip -a就是针对这种情况而设计的。它不仅会为您剥离^Z,还会在必要时修复行结尾。

$ unzip -j -p -qq z.zip a.txt | od -c
0000000   a   b   c  \r  \n   d   e   f  \r  \n 032
0000013

$ unzip -j -p -qq z.zip b.txt | od -c
0000000   g   h   i  \r  \n   j   k   l  \r  \n 032
0000013

$ unzip -j -p -qq z.zip | od -c
0000000   a   b   c  \r  \n   d   e   f  \r  \n 032   g   h   i  \r  \n
0000020   j   k   l  \r  \n 032
0000026

$ unzip -j -p -qq -a z.zip | od -c
0000000   a   b   c  \n   d   e   f  \n   g   h   i  \n   j   k   l  \n
0000020