ファイルのバイトオフセットがある。
このバイトの行番号を提供するツールはありますか?
例、ファイル:
_001
002
003 <<-- first zero on this line is byte 8
004
_
バイトオフセット_8
_があると、行__3
_になります。
行番号を見つけるためにこのようなものを使用できると思います:
a。 tail -c+(offset + 1) file | wc -l
、ここでは_+1
_ tail
は1から数えるので.
b。 _wc -l file
_
c。次に、_tail -n+num
_で、num
は_a - b + 1
_です。
しかし... num
を直接提供できるかなり一般的なツールはありますか?
編集、エラー:またはより明白な:
_head -c+offset file | wc -l
_
あなたの例では、
001
002
003
004
バイト番号8は2番目の改行であり、次の行の0
ではありません。
以下は、$b
バイト後の完全な行数を示します。
$ dd if=data.in bs=1 count="$b" | wc -l
b
を8に設定して2
を報告し、b
を7に設定して1
を報告します。
ここでの使用方法であるdd
ユーティリティは、ファイルdata.in
から読み取り、サイズ1バイトの$b
ブロックを読み取ります。
以下のコメントで「イカルス」が正しく指摘しているように、bs=1
の使用は非効率的です。この特定のケースでは、bs
とcount
を交換する方が効率的です。
$ dd if=data.in bs="$b" count=1 | wc -l
これは最初のdd
コマンドと同じ効果がありますが、$b
バイトの1ブロックのみを読み取ります。
wc
ユーティリティは改行をカウントし、Unixの「行」は常に改行で終了します。したがって、上記のコマンドは、b
を12未満の値に設定した場合でも、2
と表示されます(次の改行)。したがって、探している結果は、上記のパイプラインレポートの数に1を加えたものになります。
これにより、ASCIIテキストの前にある、ファイルのバイナリblob部分のランダムな改行もカウントされます。ASCIIビットの開始位置がわかっている場合は、 skip="$offset"
をdd
コマンドに追加できます。ここで、$offset
はファイルにスキップするバイト数です。
現在のところ、そのような専用のツールはありませんが、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
これは非常に素早く簡単なスクリプトです。ファイルが空であるかどうかはチェックしないため、空でないファイルでのみ機能します。
指定されたオフセットが合計内にある場合は、表示されたバイトを追跡し、現在の行番号を出力します。
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
_を削除し、その数を返します