Just do IT

思うは招く

lsコマンドの結果を自作wcコマンドでカウント Ruby基礎#23

やりたいこと

ターミナルのls -lコマンドの結果を自分で作ったwcコマンドにかけて行数・単語数・容量を表示させたい。

つまり以下の処理をしたい。

ls -l | wc

コード

# 標準入力を受け取る
input = $stdin.read

# 行数を取得
def load_lines(str)
  str.count("\n")
end

# 単語数を取得
def load_words(str)
  str.split(/\s/).reject(&:empty?).size
end

# バイト数を取得
def load_bytes(str)
  str.bytesize
end

def all_data(input)
  lines = load_lines(input) # 行数
  words = load_words(input) # 単語数
  bytes = load_bytes(input) # バイト数
  
  print lines.to_s.rjust(8)
  print words.to_s.rjust(8)
  print bytes.to_s.rjust(8)
  puts
end

all_data(input)

説明

wcコマンドは、オプションなしだと「行数・単語数・容量(バイト数)」の順で表示する。

標準入力を受け取る

input = $stdin.read

これで標準入力を読み込み、文字列でinputに保存する。 文字列で取得するのがポイント。

行数

wcコマンドは行数というより、改行文字の数を数える仕様になっている。よって、改行文字である\nを数えてやればよい。

def load_lines(str)
  str.count("\n")
end

単語数

wcコマンドの単語数の定義は、空白や改行文字で区切った単語のこと。

def load_words(str)
  str.split(/\s/).reject(&:empty?).size
end

取得した文字列をsplitメソッドにかけ、\s+で区切って配列に入れる。\sは空白を意味する。

空文字列があったらいけないので、.reject(&:empty?)で要素がエンプティ(空)だったら削除。

その後、sizeメソッドで要素数、つまり単語数を数える。

容量(バイト数)

def load_bytes(str)
  str.bytesize
end

bytesizeメソッドで容量(バイト数)をカウントできる。

表示

  print lines.to_s.rjust(8)
  print words.to_s.rjust(8)
  print bytes.to_s.rjust(8)

最後に、wcコマンドの表示方式に合わせる。

ls -l | wc
       7      56     398

これは右に寄せているので、rjustメソッドが使えそう。 ただし、各メソッドの戻り値は数値のため、rjustメソッドは使えない。stringオブジェクトにしか使えないからだ。

そこで、to_sメソッドでstringオブジェクトに変換する。

結果

ls -l | wc
       7      56     398
ls -l | ruby input.rb 
       7      56     398

どちらも同じ結果になった。