使用することを知っているが、tail -c +N
非常に遅く、1つのCPUコアを固定します。
leijurvs-MacBook-Pro:Downloads leijurv$ time cat /dev/zero | head -c 100000000 | shasum -a 256
a993f8c574e0fea8c1cdcbcd9408d9e2e107ee6e4d120edcfa11decd53fa0cae -
cat /dev/zero 0.00s user 0.02s system 4% cpu 0.471 total
head -c 100000000 0.01s user 0.03s system 9% cpu 0.470 total
shasum -a 256 0.45s user 0.02s system 99% cpu 0.469 total
leijurvs-MacBook-Pro:Downloads leijurv$ time cat /dev/zero | head -c 100000000 | tail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506 -
cat /dev/zero 0.01s user 0.03s system 0% cpu 7.241 total
head -c 100000000 0.02s user 0.03s system 0% cpu 7.240 total
tail -c +2 7.20s user 0.03s system 99% cpu 7.247 total
shasum -a 256 0.51s user 0.04s system 7% cpu 7.247 total
leijurvs-MacBook-Pro:Downloads leijurv$
head
とても良いです。私はshasumを使って最初の100MBに対して0を得ましたhead
。 0.47秒かかりました。
tail -c +2
以前は最初のバイトをスキップしていましたが、突然7.2秒かかりました。
tail
この間、1つのCPUコアが固定されます。
どうやってできるか表現的にストリームの最初のNバイトをスキップしますか?
答え1
ファイルを入力する前にファイルの最初のバイトをスキップするにshasum
はzsh
:time
time cat /dev/zero | head -c 100000000 |
(LC_ALL=C read -u0 -k1 && shasum -a 256)
これは追加のプロセスがなく、最初のバイトがパイプから読み取られることを意味します。read
始める前にshasum
。
それはLC_ALL=C read -u0 -k1
まさにread
ing1
文字です(k
ここでは鍵最初は、read -k
キー入力が端末から読み取られます。ここでの文字は、LC_ALL=C
ファイル記述子のu
ニット番号0
(stdin;ここでは端末ではなくストリームから読み取ることを明確にするため)のおかげでシングルバイトです。
シェルを使用すると、bash
次のようになります。read
コマンドはですLC_ALL=C IFS= read -rd '' -n1
。
zshに対応するのはread -k
一般的ですが、read -N
NULバイトを含む入力には機能せず、bash
単にread
ストライピングにすぎません(また、-N
ksh93からコピーしたものは比較的新しい追加エントリであり、macosの古代バージョンのbashでは使用できません)。区切り文字をNULバイト(ここでは空の文字列で示されている)に設定することでd
これを防ぐことができます。最初のNULで区切られたレコードから1文字を読み取ります-n1
(再バイトを生成することによって)。LC_ALL=C
ただし、これは他のバイト数に適応しないことを意味します-rd '' -n2
。最初のバイトが0の場合、バイトをスキップします。
他のシェルの場合は、read
コマンドをdd bs=1 count=1 > /dev/null 2>&1
(change、1バイト以上スキップしないcount
でください)に置き換えることができます。また、一緒に動作しますbs
head -c 1 > /dev/null
一部head
非標準オプションをサポートしていますが、-c
すべてではありませんが(特にFreeBSDではないため、おそらくmacOSではない可能性があります)、一部はより少ないバイトの出力が要求されても、固定サイズのチャンクで入力を読み取ります。ただし、上記とは異なり、対応するread
1バイトを読み取ることができない場合は、失敗した終了ステータスを報告しないため、いずれにせよshasum
実行されます。
チェックサムがパイプの代わりに通常のファイルである場合は、次のことができます。綱渡りより効率的です(複数バイトをスキップする必要があると仮定)。救うファイルからスキップした部分を読み取って削除するのではなく(静止zsh
構文):
zmodload zsh/system
{ sysseek 1234567 && shasum -a 256; } < some-big-file
最初の1234567バイトをスキップします。
またはksh93を使用してください。
shasum -a 256 < some-big-file <#((1234567))
他の殻と一部dd
(私はmacOSの実装を知りません)次のことができます。
{ dd bs=1 skip=1234567 count=0 2> /dev/null; shasum -a 256; } < some-big-file
ただし、count=0
ポータブルで使用することはできません。 countが0の場合、すべてのdd
実装がここで作業を実行するわけではありません。一部ではこのように解釈することもあります。lseek()
count=infinity
答え2
Mac OSXはtail
遅いです。
brew install coreutils
gtail
次に、トラブルシューティングのために切り替えます。
leijurvs-MacBook-Pro:~ leijurv$ time cat /dev/zero | head -c 100000000 | tail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506 -
cat /dev/zero 0.01s user 0.03s system 0% cpu 7.153 total
head -c 100000000 0.02s user 0.03s system 0% cpu 7.152 total
tail -c +2 7.07s user 0.03s system 99% cpu 7.159 total
shasum -a 256 0.51s user 0.06s system 7% cpu 7.154 total
leijurvs-MacBook-Pro:~ leijurv$ time cat /dev/zero | head -c 100000000 | gtail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506 -
cat /dev/zero 0.00s user 0.02s system 4% cpu 0.497 total
head -c 100000000 0.02s user 0.08s system 18% cpu 0.496 total
gtail -c +2 0.05s user 0.10s system 30% cpu 0.496 total
shasum -a 256 0.47s user 0.02s system 99% cpu 0.496 total
leijurvs-MacBook-Pro:~ leijurv$