Lấy số dòng từ byte bù


12

Có byte bù cho một tập tin.

Có một công cụ cung cấp số dòng cho byte này không?

  • Số byte bắt đầu bằng 0, như trong: byte đầu tiên là 0 chứ không phải 1.
  • Số dòng bắt đầu bằng 1.
  • Tệp có thể có cả văn bản đơn giản, các đốm màu "nhị phân", các ký tự đa dòng, v.v. Nhưng phần tôi quan tâm: Kết thúc tệp, chỉ có ASCII.

Ví dụ, tập tin:

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

Có byte bù 8sẽ cho tôi dòng 3.

Đoán tôi có thể sử dụng một cái gì đó như thế này để tìm số dòng:

 a. tail -c+(offset + 1) file | wc -l, Đây +1tailđếm từ 1.
 b. wc -l file
 c. Sau đó, tail -n+num nơi numa - b + 1

Nhưng ... có một công cụ khá phổ biến có thể cung cấp cho tôi numtrực tiếp không?


Chỉnh sửa, err: hoặc rõ ràng hơn:

head -c+offset file | wc -l

2
Tệp nhị phân không có dòng.
Kusalananda

@Kusalananda: Các dòng trong ngữ cảnh này là dữ liệu được phân tách bằng 0x0abyte.
dùng367890

3
Có lẽ không phải những gì bạn đang hỏi, nhưng Vim có chức năng cho nó. Nó đếm offset từ 1, vì vậy : :echo byte2line(offset+1).
Satō Katsura

@SatoKatsura: Vâng, và cảm ơn. Đã thử với vim đầu tiên. Nhưng ngay cả với vim -bvim+ set binary+ mở tệp, nó đã bị hỏng. (Ah. Đột nhiên tôi nhớ lại plugin nào làm nó rối tung lên). Nhưng, dù sao đi nữa, khi tôi sử dụng nó theo đợt và kết hợp với một loạt các kịch bản, Vim đã sớm bị bỏ rơi. Nhưng dù sao +1.
dùng367890

@ user367890 Một tệp nhị phân có thể có 0xabất cứ nơi nào. Khái niệm các dòng trong một tệp nhị phân là vô nghĩa.
dùng207421

Câu trả lời:


14

Trong ví dụ của bạn,

001
002
003
004

byte số 8 là dòng mới thứ hai, không phải 0trên dòng tiếp theo.

Sau đây sẽ cung cấp cho bạn số lượng dòng đầy đủ sau $bbyte:

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

Nó sẽ báo cáo 2với bthiết lập thành 8 và nó sẽ báo cáo 1với bthiết lập thành 7.

Các ddtiện ích, cách nó được sử dụng ở đây, sẽ đọc từ tập tin data.in, và sẽ đọc $bcác khối có kích thước 1 byte.

Như "icarus" chỉ ra đúng trong các ý kiến ​​dưới đây, sử dụng bs=1là không hiệu quả. Trong trường hợp cụ thể này, hiệu quả hơn là trao đổi bscount:

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

Điều này sẽ có tác dụng tương tự như ddlệnh đầu tiên , nhưng sẽ chỉ đọc một khối $bbyte.

Các wcdòng mới đếm tiện ích, và một "dòng" trong Unix luôn kết thúc bằng một dòng mới. Vì vậy, lệnh trên vẫn sẽ nói 2nếu bạn đặt bở mức thấp hơn 12 (dòng mới sau). Do đó, kết quả mà bạn đang tìm kiếm là bất cứ con số nào trong các báo cáo đường ống trên, cộng với 1.

Điều này rõ ràng cũng sẽ tính các dòng mới ngẫu nhiên trong phần blob nhị phân của tệp trước văn bản ASCII. Nếu bạn biết bit ASCII bắt đầu từ đâu, bạn có thể thêm skip="$offset"vào ddlệnh, $offsetsố byte được bỏ qua trong tệp.


@don_crisstihead: unknown option -- c
Kusalananda

@Kusalananda Bạn đang sử dụng đầu BSD, các tùy chọn có khác nhau
Sergiy Kolodyazhnyy

@Serg :-) Tôi biết điều đó. Chúng tôi không biết OP sử dụng những gì, vì vậy tôi đang gắn bó với POSIX.
Kusalananda

1
Như tôi đã đề cập trong Q: số byte bắt đầu bằng 0, không phải 1, do đó 8 == 0 ...
user367890

@ user367890 Trong trường hợp đó, sử dụng $(( b - 1 )).
Kusalananda

4

Hiện tại không có công cụ chuyên dụng nào như vậy, mặc dù nó có thể được thực hiện khá dễ dàng trong 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)

Cách sử dụng rất đơn giản:

line4byte.py <FILE> <BYTE>

Chạy thử nghiệm:

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

Đây là một kịch bản rất nhanh chóng và đơn giản. Nó không kiểm tra xem tệp có trống hay không, vì vậy nó chỉ hoạt động trên các tệp không trống.


4

Theo dõi các byte được nhìn thấy và phát ra số dòng hiện tại nếu phần bù đã cho nằm trong tổng:

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

Hoặc ở độ dài:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.