바이트 오프셋에서 라인 번호 가져 오기 0으로 시작하는 바이트

파일에 대한 바이트 오프셋이 있습니다.

이 바이트의 줄 번호를 제공하는 도구가 있습니까?

  • 다음과 같이 0으로 시작하는 바이트 수 : 첫 번째 바이트는 0이 아니라 1입니다.
  • 1로 시작하는 줄 번호
  • 파일에는 일반 텍스트, “이진”얼룩, 멀티 바이트 문자 등이 포함될 수 있습니다. 그러나 관심있는 섹션 : 파일 끝, 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
 씨. 그런 tail -n+numnum입니다a - b + 1

그러나 … 나를 num직접 줄 수있는 상당히 일반적인 도구가 있습니까?


편집, 오류 : 또는 더 명백한 :

head -c+offset file | wc -l



답변

귀하의 예에서

001
002
003
004

바이트 번호 8은 0다음 줄이 아닌 두 번째 줄 바꿈 입니다.

다음은 $b바이트 이후 전체 줄 수를 제공합니다 .

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

그것은보고 2b8로 설정하고 그것을보고 1b7로 설정합니다.

dd유틸리티는 여기에서 사용되는 방식으로 파일 data.in에서 읽고 $b1 바이트 크기의 블록을 읽습니다 .

아래의 설명에서 “icarus”가 올바르게 지적했듯이 사용하는 bs=1것은 비효율적입니다. 이 특별한 경우에는보다 효율적으로 교체 bs하고 count:

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

이것은 첫 번째 dd명령 과 같은 효과가 있지만 한 블록의 $b바이트 만 읽습니다 .

wc유틸리티는 줄 바꿈을 계산하며 Unix의 “줄”은 항상 줄 바꿈으로 종료됩니다. 따라서 위의 명령은 12보다 작은 값 2을 설정 하면 여전히 표시됩니다 b(다음 줄 바꿈). 따라서 찾고있는 결과는 위의 파이프 라인 보고서 수에 1을 더한 값입니다.

이것은 분명히 파일의 바이너리 BLOB 부분에서 ASCII 텍스트 앞에 나오는 임의의 줄 바꿈을 계산합니다. 아스키 비트가 시작 위치를 알았다면, 당신은 추가 할 수 있습니다 skip="$offset"받는 dd명령 $offset바이트의 수가 파일로 건너 뛸 수 있습니다.


답변

파이썬에서는 상당히 쉽게 수행 할 수 있지만 현재 이와 같은 전용 도구는 없습니다.

#!/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

이것은 매우 빠르고 간단한 스크립트입니다. 파일이 비어 있는지 확인하지 않으므로 비어 있지 않은 파일에서만 작동합니다.


답변

표시된 바이트 수를 추적하고 주어진 오프셋이 합계 내에 있어야 현재 행 번호를 내 보냅니다.

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;


답변

$perl -0nE 'say substr($_,0,8)=~ y/\n//'  ex
2
  • perl -0nE exp입력을 비방하고 $_exp를 실행
  • substr(string,0,8) 처음 8 바이트를 선택합니다
  • y/\n//를 제거 \n하고 번호를 반환

답변