我需要抓取长文本文件的第一行,以便对较小的文件进行一些错误修复(Python 脚本不会按预期消化大文本文件)。然而,为了使错误修复有意义,我确实需要这些行是完美的副本,基本上是逐字节的,并找出字符编码、行尾字符、不可见字符或不存在的任何潜在问题。原来的txt.以下简单的解决方案是否可以实现这一点,或者我会使用 的输出丢失一些东西head
?
head infile.txt > output.txt
现在发布了关于带有head
, , or else的二进制副本的更一般性问题dd
这里。
答案1
答案2
显然,head
当它不是文本文件时,它的输入确实会出现乱码:
$ wc /bin/ls
431 3454 126496 /bin/ls
$ head -n 431 /bin/ls > a
wc a
431 3447 125378 a
$ diff a /bin/ls
Binary files a and /bin/ls differ
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099 /bin/ls
de032f5aa5ef356fb7d5ab4dc622df2e a
$ wc -c /bin/ls a
126496 /bin/ls
125378 a
Stéphane Chazelas 在评论中提出了一个很好的观点:
wc -l
报告换行数。/bin/ls
在最后一次出现 后可能有更多字节0xa
,这head -n 431
不会输出。 GNU 工具(您似乎正在使用)通常可以处理二进制数据(NUL 字节和任意长的行)。
所以,使用时输出错误的原因head -n
是最后一个字符后面有多余的数据\n
。查看 GNU 的源代码head
,我可以确认按行读取的函数和按字节读取的函数都使用相同的safe_open()
调用,因此它们能够返回的内容之间确实不应该有任何区别。这表明使用 GNU 实现head
(通常在大多数使用 Linux 的非嵌入式操作系统中发现)是相当安全的。
man head
但是,如果您告诉它在字节而不是行上工作(来自),它看起来可以正常工作:
-c, --bytes=[-]NUM
print the first NUM bytes of each file; with the leading '-',
print all but the last NUM bytes of each file
使用该-c
选项,似乎会创建相同的文件:
$ wc -c /bin/ls
126496 /bin/ls
$ head -c 126496 /bin/ls > a
$
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099 /bin/ls
42846aa64774a99f0f1feba36ec2e099 a
这也与通过以下方式获得的结果相同dd
:
$ dd if=/bin/ls of=a bs=126496 count=1
1+0 records in
1+0 records out
126496 bytes (126 kB, 124 KiB) copied, 0.000469919 s, 269 MB/s
$ diff a /bin/ls
$
我无法指出任何官方文档指定在使用该-c
标志时,它总是会产生正确的二进制输出,但这似乎是一个合理的假设。
答案3
您可以使用split(1)
。这将创建许多文件,每个文件对应于文件的字节正确的切片。
示例:FILE=test ; split -b 1000 $FILE $FILE.split.
将创建 1000 字节的文件 test.split.aa 和 test.split.ab 等,cat $FILE.split.* > $FILE.recompose
并将生成与原始 $FILE 相同的 $FILE.recompose。如果您的文件大于 1000*26*26 那么您需要增加后缀长度(请参阅man split
)
有了split -l 100
它,每个文件将放置 100 行。我相当有信心这将是字节正确的。