바이트 오프셋에서 줄 번호 가져오기

바이트 오프셋에서 줄 번호 가져오기

파일의 바이트 오프셋이 있습니다.

해당 바이트의 줄 번호를 제공할 수 있는 도구가 있나요?

  • 바이트 수는 다음과 같이 0부터 시작합니다. 첫 번째 바이트는 1이 아닌 0입니다.
  • 줄 번호는 1부터 시작합니다.
  • 파일에는 일반 텍스트, "바이너리" blob, 멀티바이트 문자 등이 포함될 수 있습니다. 하지만 제가 관심을 갖는 부분은 파일 끝, ASCII만입니다.

예, 파일:

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

바이트 오프셋이 있으면 8line 이 표시됩니다 3.

나는 줄 번호를 찾기 위해 다음과 같은 것을 사용할 수 있다고 생각합니다.

 ㅏ. tail -c+(offset + 1) file | wc -l, 여기서는 1부터 계산이 +1시작됩니다  .  씨. 그래서 어디tail
wc -l file
tail -n+numnuma - b + 1

num그런데... 나에게 직접 제공 할 수 있는 상당히 일반적인 도구가 있나요 ?


편집, 오류: 또는 더 명확합니다:

head -c+offset file | wc -l

답변1

귀하의 예에서는

001
002
003
004

0바이트 번호 8은 다음 줄 이 아닌 두 번째 개행 문자입니다 .

$b다음은 바이트 뒤의 전체 줄 번호를 제공합니다.

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

2보고서 는 b8로 설정되고 보고는 7 1로 설정됩니다 b.

여기에서 사용된 유틸리티 dd는 파일에서 읽고 1바이트 크기의 블록을 data.in읽습니다 .$b

"icarus"는 아래 댓글에서 올바르게 지적했듯이 bs=1사용하기에 매우 비효율적입니다. 이 특별한 경우에는 합계를 바꾸는 것이 bs더 효율적입니다 count.

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

이는 첫 번째 명령과 동일한 효과를 가지지 만 바이트 블록 dd만 읽습니다 .$b

wc유틸리티는 Unix에서 "라인"이 항상 끝나는 개행 문자를 계산합니다. 따라서 12보다 낮은 값(개행 문자 아래)으로 2설정하면 위 명령이 계속 표시됩니다. b따라서 찾고 있는 결과는 위 파이프라인이 보고하는 숫자에 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하고 반환합니다.

관련 정보