从字节偏移量获取行号


12

具有文件的字节偏移量。

有没有提供此字节行号的工具?

  • 字节计数从零开始,例如:第一个字节为0而不是1。
  • 行号以1.开头
  • 文件可以同时包含纯文本,“二进制” blob,多字节字符等。但是我感兴趣的部分:文件结尾,仅包含ASCII。

示例文件:

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

具有字节偏移量8将使我行3

猜猜我可以用这样的东西来找到行号:

 一个。tail -c+(offset + 1) file | wc -l,这里+1tail从1计数
 湾 wc -l file
 C。那么tail -n+num 这里numa - b + 1

但是...是否有可以num直接给我的相当普遍的工具?


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

head -c+offset file | wc -l

2
二进制文件没有行。
库沙兰丹

@Kusalananda:在此上下文中,行是用0x0a字节分隔的数据。
user367890

3
可能不是您要的内容,但Vim具有此功能。它从1开始计算偏移量:echo byte2line(offset+1)
聪桂

@SatoKatsura:是的,谢谢。首先尝试使用vim。不过,即使vim -bvim+ set binary+打开文件就被损坏了。(啊,突然我想起哪个插件搞砸了)。但是,无论如何,由于我成批使用它,并与一系列脚本结合使用,Vim早就被放弃了。但是无论如何+1。
user367890

@ user367890二进制文件可以在0xa任何地方。二进制文件中的行的概念是没有意义的。
user207421 '02

Answers:


14

在您的示例中

001
002
003
004

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

下面将为您提供$b字节后的全行数:

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

将报告2b设为8,将报告1b设置为7。

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

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

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

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

wc实用工具会计算换行符,而Unix中的“行”始终以换行符终止。因此,上面的命令仍会说2是否设置b为小于12的值(以下换行符)。因此,您要寻找的结果是上述管道报告的任意数字加上1。

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


@don_crisstihead: unknown option -- c
库萨兰达

@Kusalananda您正在使用BSD磁头,选项有所不同
Sergiy Kolodyazhnyy

@Serg :-)我很清楚。我们不知道tho使用什么,所以我坚持使用POSIX。
库萨兰达

1
正如我在Q中提到的:字节计数以0而不是1开头,因此8 == 0 ...
user367890

@ user367890在这种情况下,请使用$(( b - 1 ))
库萨兰达

4

目前没有像这样的专用工具,尽管可以在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

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


4

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

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;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.