<ruby> grep ぽいことするやつ作った
新しいMac買ってしまった
お金やばいのも多少あるけどそれ以上にサクサク動いて快適
grepぽいことするやつ作った
grepってコマンドあるじゃないですか。
ファイルの中身とか検索するあれ
あれってwindowsで使えないじゃないですか
互換はあるけど使い方で見れば別物なのでなんともっていう
そこで同じように使うとなったらプログラム書くしかなくねとなり書きました。
目次
- 今回の目的
- 作ったもの
2.1 ファイルの取得
2.2 取得したファイルの検索
2.3 検索結果の出力
3.できたもの
1.今回の目的
目的はほぼ最初のところに書いてしまっている。
なのでさらに詳細まで書きます。
今回の最終的な目的としてはドラッグ&ドロップで対象ファイル選んでキーワード、条件に一致するやつを検索するようなものを完成させるのが目的になっています。
最初っから一気に完成形を目指せる自信は皆無なのでまずはコマンドで使えるようになればいいかなということで作成します。
今回のゴールとしては
grep-test poolbooyer$ grep -n index data/* data/sample1.txt:3:index data/sample1.txt:4:index data/sample1.txt:5:index data/sample1.txt:6:/index.htm data/sample1.txt:7:index data/sample1.txt:9:/index.html data/sample1.txt:10:/index.htm data/sample2.txt:3:/assets/js/index.js ...
的なものを作ります。
ただ、このままだと微妙に見づらさがあるので、出力形式を以下のようにします。
file名 行数:ヒットした文字列 行数:ヒットした文字列 file名 行数:ヒットした文字列 ...
なんかいい感じに同じファイル単位でまとめて表示するようにします。
2.作ったもの
ということで実装していきました。
今回の流れとしては
ファイル一覧取得->ファイル内容取得->ファイル内部検索->結果出力
でいきます。
この時検索する語句と対象はコマンドライン引数で引っ張ってきます。
ruby serch-eg.rb フォルダ名 検索語句
最初二つはDirで取得して、fileopenなので今回は
ちゃんと書きます
2.1 ファイルの取得
まずはファイルの情報を取得します。
検索対象のフォルダの中身を確認します。
その後、検索対象の中身を取得します。
今回はファイル名とファイルの中身を1つの配列で返すようにしました。
まずはフォルダの中身の確認と取得するところを呼び出すところまで
# 引数のフォルダの中身を確認する fi=Dir::entries(ARGV[0]) # 結果を取扱う配列 data=[] # フォルダ中身全てに対して for i in 0..(fi.length-1) do if fi[i].length>2 then # ファイルの中身を呼び出して配列に追加 data.push(read_file(ARGV[0]+fi[i])) end end
read_fileに渡しているARGV[0]+fi[i]はファイルへのパスです
その上で読み出すプログラム
def read_file(path) r_data=[] r_data[0]=path File.open(path,"r") do |f| r_data[1]=f.read end # 読み込んだデータとファイルのパスを返す return r_data end
的な感じです
2.2 ファイルの検索
読み込んだ情報をもとにしてその中身を検索します。
targetには読み込んだデータ、queryには検索する文字列が入っています。
def search_infile(target,query) # 検索結果 res=[] for i in 0..(target.length-1) do # 文字列を含むか検索 if target[i].include?(query) then res[i]=true else res[i]=false end end # 検索結果を返す return res end
2.3 結果の出力
検索と出力が1つのプログラムにまとめてます。
ここは分割する予定です。
検索するプログラムにコマンドライン引数で受け取った検索文字列と読み込んだファイルのデータを渡すところから
query=ARGV[1] search_each(data,query)
そして、2.2のプログラムを呼び出します
def search_each(data,query) data.each do |line| # line[1]にあるファイルの中身を改行単位で配列に分割 target=line[1].split("\n") # 検索結果を取得 res=search_infile(target,query) # 検索結果をカウント count=0 # ファイル名称を出力 puts line[0] # 検索結果を参照 for i in 0..(res.length-1) do # 一致していたら出力 if res[i]==true then puts "L#{i+1}: #{target[i]}" else count+=1 end end # 1つも一致しなかったら"Not found"と出力 if count==(res.length) then puts "Not found" end # ファイルの結果の間に一行あける puts "" end end
3.できたもの
ということでこれを実行するとこんな感じになります
grep-test poolbooyer$ ruby ./searcher/search-eg.rb data/ inde data/sample4.txt L1: index L2: /index.htm L3: index L7: index L8: /assets/js/index.js L9: index L10: /index.html data/sample5.txt L1: inde ... grep-test poolbooyer$ ruby ./searcher/search-eg.rb data/ fuga data/sample4.txt Not found data/sample5.txt Not found data/sample1.txt ...
これで期待する結果の出方になりましたー!
ちなみに今回のコードは以下にあります
github.com
(search/に入ってます、検索対象にするデータはscript/generator.rbを使って生成してます)
まだ直しが入る予定なので今回はここまで