`wc -l`はどのように機能しますか?


11

大きなファイルを読み取る必要があり、それを読み取る前に、ファイル内の合計行数(数百万単位)を知る必要があります。

私は多くの解決策を実装し、見つけました。しかし、私の検索中、私はどのようにwc -l機能するのかを見ようと考えていました。Googleで何も見つかりませんでした。

私は自分の問題の解決策を見つけましたが、それでもwc -l数秒で9,200万行のファイルの行数を計算できるので、それがどのように機能するかを知りたいのです!

どうやって?


回答:


20

ファイル全体を読み取り、行末の数をカウントします。行末を数えるのは本当に安いです。費やされる時間のほとんどは、ファイルの読み取りです。ファイルが(ほとんど)バッファキャッシュにある場合、それも安くなります。それ以外の場合は、ファイルストレージの速度によって異なります。

つまり、魔法はありません。


ファイル全体を読み取り、行末の数を数えますか?行末に到達するためには、基本的に行末まで行全体を読みませんか?これは、ファイル全体を読み取ることを意味しますよね?
detraveller 2013

@detraveller:はい、私が言ったように、ファイル全体を読み取ります。1行ずつ、またはすべてを一度に読み取ることはありませんが、すべての文字を読み取り、それらの文字の数を行末文字としてカウントします。
rici 2013

7

WCは、ファイルをrawバイトのブロックで読み取るだけです(ファイルが配置されている基本のファイルシステムの自然なブロックサイズの倍数が望ましい)。
次に、行末文字をカウントしてバッファをスキャンします。(-l出力以外の情報が必要な場合に備えて、スペース、タブ、フォームフィード、その他の特殊文字もカウントされます。)

ディスクからの読み取りは、速度の点でコストのかかる部分です。それに比べて、バッファのスキャンには無視できるほどの時間がかかります。

たとえば、1行あたり平均100文字の9000万行があるとします。
それは約9.000.000.000文字または約860 MBです。
SATA-3Gb / sドライブを備えたまともなPCなら、10秒未満で完了します。比較的遅いファイルシステムでも、他のアクティビティが同時に進行している場合。
パフォーマンスチューニングと最適化されたファイルシステムを備えた高速マシンは、SATA-6GやSSDドライブに頼らなくても、5秒未満で実行できます。


行末(\n)文字をカウントするバッファをスキャンするだけです-"-l、--lines print newline counts \ n \"-Extracted fromwc.c
Rahul Patil

@RahulPatilほとんどの実装では、改行を数えるだけではありません。上記のトップコメントに記載されている例を参照してください。これは、Linuxコアユーティリティで使用されるwcのソースです。
Tonny 2013

はい..私はそれを見wc -lました..申し訳ありませんが、.. について質問したので申し訳ありません...
Rahul Patil

3

フリーソフトウェアの世界へようこそ。あなたはいつでもソースコードを見ることができます

私はCプログラマではないことを認めざるを得ませんが、私は実際にコードを説明できる人ではありません(私私自身に興味を持っています)。

私が知っていることは、wcはファイル自体を開かず、OSにそれを開くように要求するため、これはOSに、そしてもちろんファイルがどのように格納されるかに大きく依存します。それとは別に、ファイル全体を一度に読み取ろうとしないなど、正しいプログラミング方法が整っている必要があると思います。


「ファイル全体を一度に読み取ろうとしない」とはどういう意味ですか?
detraveller 2013

つまり、ファイルをメモリに、たとえば単一の文字列/配列にロードすることです。Perlコミュニティでは、これは丸呑みと呼ばれ、数行を読み取ることがわかっている場合は問題ありませんが、非常に大きなファイルを一度にメモリにフィードすることは、あまりお勧めできません。
Alois Mahdal 2013

1
一方、たとえば64 KiBを読み取って改行を数え、それを破棄して繰り返すことができます。これにより、ファイルのサイズに関係なく、最大で64 KiBを超えるものを使い果たしてしまいます。(改行が2バイトになり、2つのチャンクに分かれることに気づくと、それほど簡単ではありません。ここからが楽しいところです)
アロイスマダル

重要ではないが、「wcはファイル自体を開かないが、OSに開くように要求するため」 -それが何を意味するのかわからないが、これが正しいとは思えない。それは確かにそれ自体ですべての文字を読んでいます。
Arjan 2013

2
@Arjanただし、正確に言うと、組み込みシステムを除いて、プログラムが実際に読み取りを行うことはほとんどありませんが、カーネルとOSの重要な点は、それがそれらのために機能することです。実際、open()、close()、read()(Linux、Windows、ソケット、ファイルなど)はすべて、実際のプログラムが内部の仕組みを理解していないシステムコールです。
Alois Mahdal 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.