ファイル内のヌル区切りのアイテムを数える


8

find -print0処理するファイルのリストを一時ファイルに保存するために使用するシェルスクリプトがあります。ロギングの一部として、見つかったファイルの数を出力したいので、その数を取得する方法が必要です。-print0オプションが安全のために使用されていなかった場合、私wc -lはカウントを取得するために使用できます。


回答:


11

いくつかのオプション:

tr -cd '\0' | wc -c

tr '\n\0' '\0\n' | wc -l      # Generic approach for processing NUL-terminated
                              # records with line-based utilities (that support
                              # NUL characters in their lines like GNU ones).

grep -cz '^'                  # GNU grep

sed -nz '$='                  # recent GNU sed, no output for empty input

awk -vRS='\0' 'END{print NR}' # not all awk implementations

最後のNUL文字の後にデータを含む入力(またはNUL文字のない空でない入力)の場合、trアプローチは常にNUL文字の数をカウントしますが、awk/ sed/ grepアプローチはそれらの余分なバイトの追加レコードをカウントします。


これらを5 GBのランダムデータで測定しました(head -c 5G /dev/urandom > f)。結果: grep 1.7s(と同じgrep -Fcz '')•tr + wc-c 7.7s•tr + wc-l 7.4s•sed 34.7s•awk 1m11.7s
Socowi

@ Socowi、YMMVの実装とロケール。GNU awkでは、ロケールC(またはマルチバイト文字を使用しないもの)に設定する必要があります。LC_ALL=C awk ... < f
StéphaneChazelas

ヒントをありがとう。私はすでにそれがスピードアップしなかっLC_ALL=Csortところを使っていたので、幸いにも私はまだ前のファイルを持っています:LC_ALL=C awk ...6.7秒かかります。
ソコウィ

4

私が考えることができた最良の方法は、を使用することgrep -zc '.*'です。これは機能しますが、何にでも一致するパターンでgrepを使用するのは間違っています。


1

perl

perl -0ne 'END {print $.}'

または:

perl -nle 'print scalar split "\0"'

または:

perl -nle 'print scalar unpack "(Z*)*", $_'

最後のNULの後にデータがある場合、最初のレコードは追加のレコードをカウントします。他の2つは、入力に改行文字が含まれている場合は機能しません。
ステファンChazelas

@StéphaneChazelas:ああ、悪い。改善をお願いできますか?
cuonglm 2014年

私は最初のレコードをそのまま保持し、それが(とは逆にwc -l)区切られていないレコードを数えるという事実をメモとして(必要に応じて)言及します。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.