从字节偏移量获取行号

从字节偏移量获取行号

具有文件的字节偏移量。

有没有一个工具可以给出该字节的行号?

  • 字节计数从零开始,如下所示:第一个字节是 0 而不是 1。
  • 行号从 1 开始。
  • 文件可以有纯文本、“二进制”blob、多字节字符等。但我感兴趣的部分:文件结尾,只有 ASCII。

示例,文件:

001
002
003  <<-- first zero on this line is byte 8
004

有字节偏移量8会给我 line 3

我想我可以用这样的东西来查找行号:

 A。tail -c+(offset + 1) file | wc -l,此处从 1+1开始tail计数
 。wc -l file
 C。那么在tail -n+num 哪里numa - b + 1

但是......有没有一个相当常见的工具可以num直接给我?


编辑,错误:或更明显的:

head -c+offset file | wc -l

答案1

在你的例子中,

001
002
003
004

字节号 8 是第二个换行符,而不是0下一行。

$b以下将为您提供字节后的整行数:

$ dd if=data.in bs=1 count="$b" | wc -l

它将报告2设置b为 8,并将报告设置1b7。

dd实用程序(按照此处使用的方式)将从文件中读取data.in,并将读取$b大小为 1 字节的块。

正如“icarus”在下面的评论中正确指出的那样,使用bs=1效率很低。在这种特殊情况下,交换bs和会更有效count

$ dd if=data.in bs="$b" count=1 | wc -l

这将与第一个命令具有相同的效果dd,但只会读取一个$b字节块。

wc实用程序对换行符进行计数,Unix 中的“行”始终以换行符结尾。因此,2如果您设置b为低于 12 的值(以下换行符),上面的命令仍然会显示。因此,您要查找的结果是上述管道报告的任何数字加 1。

显然,这也会计算文件中 ASCII 文本之前的二进制 blob 部分中的随机换行符。如果您知道 ASCII 位从哪里开始,则可以添加skip="$offset"dd命令中,其中$offset是要跳到文件中的字节数。

答案2

目前还没有这样的专用工具,尽管在 python 中可以相当容易地完成:

#!/usr/bin/env python3
import sys
import os

offset = int(sys.argv[2])
newline = 1
with open(sys.argv[1]) as fd:
    fd.seek(offset)
    while True:
        try:
            byte = fd.read(1)
            if byte == '\n': newline+=1
            #print(byte)
            offset = offset - 1
            fd.seek(offset)
        except ValueError:
            break
print(newline)

用法很简单:

line4byte.py <FILE> <BYTE>

测试运行:

$ cat input.txt
001
002
003
004
$ chmod +x ./line4byte.py                                                     
$ ./line4byte.py input.txt 8                                                  
3

这是一个非常快速且简单的脚本。它不会检查文件是否为空,因此它仅适用于非空文件。

答案3

如果给定的偏移量在总和之内,则跟踪看到的字节并发出当前行号:

perl -E '$off=shift;while(<>){$sum+=length;if($sum>=$off){say $.;exit}}' 8 file

或者详细地说:

#!/usr/bin/env perl
use strict;
use warnings;
die "Usage: $0 offset file|-\n" if @ARGV != 2;
my $offset = shift;
shift if $ARGV[0] eq '-';
my $sum;
while (readline) {
    $sum += length;
    if ($sum >= $offset) {
        print "$.\n";
        exit;
    }
}
exit 1;

答案4

$perl -0nE 'say substr($_,0,8)=~ y/\n//'  ex
2
  • perl -0nE exp将输入吞入$_并执行 exp
  • substr(string,0,8) 选择前 8 个字节
  • y/\n//删除\n并返回其编号

相关内容