しかし、その結果を戻り値として受け取ることができない。
そこで、仕方なくC#でGrepする機能を実装してみた。
フォルダ配下をGrepする
たとえば、以下のようなHTMLファイルがフォルダ配下に複数あったとする。
<!DOCTYPE html>
<html>
<head>
<title>C#でGrep</title>
</head>
<body>
<ul>
<li><a href="./menu.html">メニュー</a></li>
<li><a href="./blog.html">ブログ</a></li>
<li><a href="./mail.html">メールフォーム</a></li>
</ul>
</body>
</html>
それをC#でサブディレクトリも対象にしてGrepする場合は、以下のような処理になる。
using System.IO;
using System.Linq;
using System.Text;
var enc = Encoding.GetEncoding("shift_jis");
foreach (var f in Directory.GetFiles(@"C:\HtmlFolder"
, "*.html"
, SearchOption.AllDirectories))
{
var grep = File.ReadAllLines(@f, enc)
.Select((s, i) => new {Index = i, Value = s})
.Where(s => s.Value.Contains("title")
|| s.Value.Contains("<a>"));
foreach (var g in grep)
{
// 表示結果
// 004:<title>C#でGrep</title>
// 008:<li><a href="./menu.html">メニュー</a>
Console.WriteLine("{0:000}:{1}", g.Index, g.Value);
}
}
こんな感じでGrepすることができる。
System.IO.Directory.GetFiles
で、指定したフォルダ配下のファイルを取得している。※
SearchOption.AllDirectories
を指定することでサブディレクトリまで検索できる。※
SearchOption.TopDirectoryOnly
を指定すれば、サブディレクトリは含まれない。System.IO.File.ReadAllLines
で、ファイルをstring型の配列として一気に読み込み、LINQを使って整形していく。Select((s, i) => new {Index = i, Value = s})
は、Enumerable.Selectを使って、配列の値とインデックスを取得して、匿名型に格納している。Where(s => s.Value.Contains(“title”))
は、Selectで抽出したValueの中に「文字列("title")」が含まれるかどうか判定している。これにより「文字列("title")」が含まれる業のみが抽出される。ここで、注意すべき点は、ReadAllLines.Where.Selectのようにしないことだ。
最初にフルイにかけちゃうと、元々のインデックスは崩れてしまい、Whereで絞りこまれたあとの配列のインデックスになってしまう。
参考
- Directory.GetFiles メソッド - MSDN
- File.ReadAllLines メソッド - MSDN
- Enumerable.Select(TSource, TResult) メソッド - MSDN
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿