Lás*_*zló 3 shell character-encoding text-processing head
我需要抓取长文本文件的第一行,以便在较小的文件上进行一些错误修复(Python 脚本没有按预期消化大文本文件)。然而,为了使错误修正有意义,我真的需要这些行是完美的副本,基本上是逐字节的,并找出字符编码、行尾字符、不可见字符或不可见字符的任何潜在问题原来的.txt 以下简单的解决方案会实现这一点,否则我会使用 的输出丢失一些东西head
吗?
head infile.txt > output.txt
Run Code Online (Sandbox Code Playgroud)
在与二进制拷贝一个更一般的问题head
,dd
或者别的现已公布在这里。
显然,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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
使用该-c
选项,它似乎创建了相同的文件:
$ wc -c /bin/ls
126496 /bin/ls
$ head -c 126496 /bin/ls > a
$
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099 /bin/ls
42846aa64774a99f0f1feba36ec2e099 a
Run Code Online (Sandbox Code Playgroud)
这也与通过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
$
Run Code Online (Sandbox Code Playgroud)
我无法指出任何官方文档指定使用该-c
标志时,它将始终产生正确的二进制输出,但这似乎是一个合理的假设。