2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

F#である範囲の特定行を範囲ごとにグルーピングする

Last updated at Posted at 2014-04-27

ログやソースコードのようなテキストファイルから、ある特定の形式の行を開始行、別の特定の形式行を終了行としてその間の範囲で特定の形式の行(複数行)を範囲ごとにグルーピングして取得したいことがたまにあります。たとえば

[START] ... ←開始行
... [ERROR] #1 ... ← 必要な行
... [INFO] ... ← 不要な行
... [ERROR] #2 ... ← 必要な行
[END] ... ←終了行
... ← 無関係な行
[START] ... ←開始行
... [ERROR] #3 ... ← 必要な行
... [INFO] ... ← 不要な行
[END] ... ←終了行

となっていたとして、必要な行(複数行)を次のようにグルーピングした(ものを他の処理で使いた)いのです。
[グループ1]
... [ERROR] #1 ... ← 必要な行
... [ERROR] #2 ... ← 必要な行
[グループ2]
... [ERROR] #3 ... ← 必要な行
...

この処理が必要になるたびに忘れてしまっていて毎回考え直しているのでメモっておこうと思ったわけで。

let re0 = new Regex(@"...") // 範囲開始行にマッチ
let re1 = new Regex(@"...") // 範囲終了行にマッチ
let re2 = new Regex(@"...") // 範囲中で取得したい行にマッチ

let trd (x, y, z) = z

use r = new StreamReader(filename, Encoding.UTF8)
seq {
    while r.Peek() >= 0 do
        yield r.ReadLine()
}
|> Seq.fold
    (fun (isInRange, currentLines, linesList) line ->
        if isInRange then
            if re1.IsMatch(line) then (false, [], linesList @ [currentLines])
            else if re2.IsMatch(line) then (true, currentLines @ [line], linesList)
            else (true, currentLines, linesList)
        else
            if re0.IsMatch(line) then (true, [], linesList)
            else (false, [], linesList))
    (false, [], [])
|> trd
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?