ファイルのバイトオフセットがあります。
そのバイトの行番号を提供できるツールはありますか?
- バイト数は次のように0から始まります。最初のバイトは 1 ではなく 0 です。
- 行番号は1から始まります。
- ファイルには、プレーンテキスト、「バイナリ」ブロブ、マルチバイト文字などを含めることができます。しかし、私が興味を持っているのは、ファイルの終わり、ASCIIだけです。
はい、ファイル:
001
002
003 <<-- first zero on this line is byte 8
004
バイトオフセットがある場合は8
ラインが表示されます3
。
私は行番号を見つけるために次のようなものを使用できると思います。
ㅏ。tail -c+(offset + 1) file | wc -l
、ここでは1から計算が+1
始まります。氏。だからどこtail
wc -l file
tail -n+num
num
a - b + 1
num
しかし、私に直接提供できるかなり一般的なツールがありますか?
編集、エラー:またはより明確です:
head -c+offset file | wc -l
答え1
あなたの例では
001
002
003
004
0
バイト番号8は、次の行ではなく2番目の改行文字です。
$b
以下は、バイトの後の完全な行番号を提供します。
$ dd if=data.in bs=1 count="$b" | wc -l
2
レポートはb
8に設定され、レポートは71
に設定されます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テキストの前にあるファイルのバイナリブロブ部分にある任意の改行文字も計算します。 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
て返します。