0

ARGF 経由でファイルを読み込んで、そのファイルに対していくつかの操作を実行しようとしています。何かを行う前に、特定の行を読み込んでその内容を検証する必要があります。

私は自分のスクリプトを次のように呼び出しています:

./main.rb < input.txt

次のように特定の行(10行目としましょう)にアクセスしようとしています:

if __FILE__ == $0

    ARGF.lineno= 10
    puts "lineno: #{ARGF.lineno}" # Prints 10 (as expected)
    puts "readline: #{ARGF.readline}" # Prints contents of line 0 instead of 10!

end

docsごとに ARGF.lineno= を手動で設定できますが、これは機能しているようです。しかし、設定したばかりの行を読み取ろうとすると、行 0 の内容が取得されます。

指定された行に到達するために行をループすることはオプションではないことに注意してください。私の入力データは数十万行の長さになる可能性があります。

助けてくれてありがとう。

4

2 に答える 2

3

メソッドのソースをlineno=見ると、入力ストリームにはまったく影響がないことがわかります。指定された値で自動行番号が上書きされるだけです。特定の行にスキップしたい場合は、独自のメソッドを作成する必要があります。

ファイルは、行としてではなく、バイトのシーケンスとして保存されることに注意してください。特定の行にスキップするには、ファイルをスキャンして行区切りを探す必要があります。

例えば:

def ARGF.skip_lines num
  enum = each_line
  num.times { enum.next }
  self
end

これを 600,000 行の 36M ファイルでテストしたところ、最初の行から最後の行まで約 1 秒でスキップできました。

入力形式を制御できる場合は、各行を特定の長さにパディングしてから、 を使用IO#seekして特定の行にジャンプできます。しかし、それには他の欠点があります。

于 2013-10-15T14:38:17.137 に答える
1

pos=アクセサーを使用したい: lineno=docs によると何もしないようです。

pos=バイトオフセットにジャンプするため、これを行うには行の長さを固定する必要があります。

考えてみると、これは理にかなっています。ストリームは、まだ読み取っていないファイルの各行に何バイトあるかを知ることができません。

于 2013-10-15T14:45:49.343 に答える